home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / network / nsclilib / ni_msg.c < prev    next >
Text File  |  1996-07-05  |  126KB  |  4,248 lines

  1. /*      
  2. * ===========================================================================
  3. *
  4. *                            PUBLIC DOMAIN NOTICE                          
  5. *               National Center for Biotechnology Information
  6. *                                                                          
  7. *  This software/database is a "United States Government Work" under the   
  8. *  terms of the United States Copyright Act.  It was written as part of    
  9. *  the author's official duties as a United States Government employee and 
  10. *  thus cannot be copyrighted.  This software/database is freely available 
  11. *  to the public for use. The National Library of Medicine and the U.S.    
  12. *  Government have not placed any restriction on its use or reproduction.  
  13. *                                                                          
  14. *  Although all reasonable efforts have been taken to ensure the accuracy  
  15. *  and reliability of the software and data, the NLM and the U.S.          
  16. *  Government do not and cannot warrant the performance or results that    
  17. *  may be obtained by using this software or data. The NLM and the U.S.    
  18. *  Government disclaim all warranties, express or implied, including       
  19. *  warranties of performance, merchantability or fitness for any particular
  20. *  purpose.                                                                
  21. *                                                                          
  22. *  Please cite the author in any work or product based on this material.   
  23. *
  24. * ===========================================================================
  25. *
  26. * File Name:    ni_msg.c
  27. *
  28. * Author:       Beatty, Gish, Epstein
  29. *
  30. * Version Creation Date:        1/1/92
  31. *
  32. * $Revision: 4.0 $
  33. *
  34. * File Description: 
  35. *   This file consists mostly of functions for creating, destroying, reading,
  36. *   and writing message structures. It also contains the high-level functions
  37. *   for reading or writing a message, as well as the lowest-level functions
  38. *   which are read, write, and error 'hooks' for the ASN library.
  39. *
  40. * Modifications:  
  41. * --------------------------------------------------------------------------
  42. * Date     Name        Description of modification
  43. * -------  ----------  -----------------------------------------------------
  44. * 5/01/92  Epstein     Added extensive in-line commentary, and removed all tabs
  45. * 5/01/92  Epstein     Modified to support un-blocked reads, by storing state
  46. *                      information and returning to the caller.
  47. * 5/11/92  Epstein     Changed MsgBuild() to free memory in the event of
  48. *                      an invalid message type; fixed MsgDestroy() to
  49. *                      return -1 rather than NULL (NULL is the wrong type);
  50. *                      added logic to allow the dispatcher to update the
  51. *                      CONID file when the value of "conid" is incremented
  52. * 6/18/92  Epstein     Added AsnIoSetBufsize() for write socket, to improve
  53. *                      network throughput.
  54. * 6/22/92  Epstein     Changed all NI_AsnRead() and NI_AsnWrite() error return
  55. *                      codes to be the negative of the absolute value of errno,
  56. *                      because errno's can be negative on Macintoshes.
  57. * 7/10/92  Epstein     Changed MsgSaveData() to set the current index
  58. *                      (mh->cur_index) to match the number of queued bytes;
  59. *                      this avoids unintentional re-reading of queued data
  60. *                      unless a read fails.
  61. * 2/12/93  Epstein     Add an argument to MsgMakeHandle() to indicate whether
  62. *                      or not a socket should be created.
  63. * 2/19/93  Epstein     Add PC-NFS 4.0 support.
  64. * 2/24/93  Epstein     Fix memory leak
  65. * 3/08/93  Epstein     Add optional client platform to service request
  66. * 3/11/93  Epstein     Add "is-alternate-list" boolean to dispatcher-list,
  67. *                      to make it easier for a dispatcher-monitor-client
  68. *                      to distinguish between primary and backup dispatchers.
  69. * 3/23/93  Epstein     Change platform conditional-compilation to include
  70. *                      the NETP_INET_ prefix, add VMS/TGV support.
  71. * 4/02/93  Epstein     Remember to initialize conid to a known value ... this
  72. *                      avoids clients connecting with all sorts of wild conid
  73. *                      values.
  74. * 4/02/93  Epstein     Add preliminary WinSock support.
  75. * 4/13/93  Epstein     Add subSet fields to toolset to support catalog
  76. *                      filtering by dispatcher.
  77. * 4/21/93  Schuler     Removed (IoFuncType) typecast on calls to AsnIoNew()
  78. *                      in order to enable compile-time type checking.
  79. * 4/21/93  Schuler     Changed implementation of NI_AsnNew(), NI_AsnWrite(), and
  80. *                      NI_ASNIOError() to use LIBCALLBACK calling convention.
  81. * 4/21/93  Epstein     Fix MsgBuild() return error (was incorrectly returning
  82. *                      FALSE instead of NULL).
  83. * 5/07/93  Epstein     Fixup NI_SetBlocking() and NI_SetNonBlocking(), which
  84. *                      had been backwards.  Also add Wollongong (TWG) support,
  85. *                      and use INVALID_SOCKET #define, per WinSock spec.
  86. * 5/25/93  Epstein     Add regional support, and add application ID to
  87. *                      service request.
  88. * 5/27/93  Epstein     Provide separate error code for ASN.1 dynamic object
  89. *                      loader failure, try to do separate PeekMessage, etc.
  90. *                      code for WinSock in the never-ending battle to fix
  91. *                      scrollbar behavior under WinSock.
  92. * 5/28/93  Epstein     Re-work Disable-vibrant code to use new pragmatic
  93. *                      "Gestalt" functions, rather than making explicit
  94. *                      calls into Vibrant.  This decouples Network Services
  95. *                      from Vibrant.
  96. * 6/02/93  Epstein     Fixup sys_errlist references to correctly use new
  97. *                      SOCK_INDEX_ERRNO macro, to accomodate yet another
  98. *                      WinSock peculiarity.
  99. * 6/07/93  Epstein     Use new timer mechanism to support "hung timeout";
  100. *                      also add new function MsgSetTimeoutHooks().
  101. *                      Also add missing revision history, derived from
  102. *                      RCS file.
  103. * 6/09/93  Epstein     Added activity hook to report network activity back
  104. *                      to an application.
  105. * 6/15/93  Epstein     Fix long-standing WinSock scrolling problem, by changing
  106. *                      NI_poll_select() to refrain from processing
  107. *                      WM_LBUTTONUP messages.  For some reason, reading these
  108. *                      messages off the queue and processing them resulted
  109. *                      in a failure to correctly interpret the WM_LBUTTONUP
  110. *                      message as an "end scrolling" message.
  111. *                      Also clean-up Windows compilation warnings.
  112. * 6/17/93  Epstein     Temporarily change NI_SetNonBlocking() to provide
  113. *                      incorrect (blocking!) semantics for TWG.  This must
  114. *                      be fixed at a later date.
  115. * 6/22/93  Epstein     Support UCX, although NI_SetNonBlocking() and
  116. *                      NI_SetBlocking() are currently completely unsupported.
  117. *                      This should be fixed at a later date if it turns out
  118. *                      that UCX actually supports these features.
  119. * 8/09/93  Epstein     Remove annoying cursor modification, except for NEWT,
  120. *                      where it may be necessary.
  121. *01/21/94  Schuler     Calls to Yield() bracketed by #ifdef WIN61/#endif
  122. *01/28/94  Schuler     Replaced "OS_MAC" with "NETP_INET_MACTCP"
  123. *01/28/94  Schuler     Defined THIS_MODULE and THIS_FILE
  124. *02/14/94  Epstein     Added encryption support
  125. *02/16/94  Epstein     Replaced Gestalt calls with SetAppProperty()
  126. *02/24/94  Epstein     Move des-key from dispinfo to login to allow ncbid
  127. *                      to send a DES key to dispatcher.  Also performed some
  128. *                      cleanup.
  129. *06/08/94  Epstein     Add messages needed for SOCKS support
  130. *06/15/94  Epstein     Add parameter to MsgWrite(), and add server-ip to
  131. *                      service request, both to accomodate SOCKS.
  132. *12/06/94  Epstein     Added connectDelay, adminInfo and motd field to
  133. *                      client<->Dispatcher communication.  Also populated
  134. *                      the priority field in the Catalog.
  135. *12/21/94  Epstein     Make use of new socket instrumentation
  136. * ==========================================================================
  137. *
  138. *
  139. * RCS Modification History:
  140. * $Log: ni_msg.c,v $
  141.  * Revision 4.0  1995/07/26  13:56:32  ostell
  142.  * force revision to 4.0
  143.  *
  144.  * Revision 1.37  1995/05/24  12:08:54  epstein
  145.  * add support for tracking of how many times a client IP has used a service within a time interval
  146.  *
  147.  * Revision 1.36  95/05/17  17:52:39  epstein
  148.  * add RCS log revision history
  149.  * 
  150. */
  151.  
  152. extern char * g_nsclient_module;
  153. #define THIS_MODULE g_nsclient_module
  154. static char *  _this_file = __FILE__;
  155. #define THIS_FILE _this_file
  156.  
  157. #include <ncbi.h>
  158. #include "ni_msg.h"
  159. #include "ni_asn.h"   /* produced by ASNTOOL */
  160.  
  161. /* macros */
  162. #if defined(NETP_INET_NEWT) || defined(NETP_INET_WSOCK)
  163. /* cooperation may be required with Vibrant to avoid runaway scrollbars */
  164. #define DisabVibrant() { Nlm_SetAppProperty("disable_vibrant", "1"); SetHourGlass(); }
  165. #define EnabVibrant()  { Nlm_RemoveAppProperty("disable_vibrant"); PopHourGlass(); }
  166. #else
  167. #define DisabVibrant() 
  168. #define EnabVibrant()
  169. #endif /* NETP_INET_NEWT */
  170.  
  171. static NIAckPtr                 readACK PROTO((void));
  172. static void                     writeACK PROTO((NIAckPtr ackp));
  173. static NINackPtr                readNACK PROTO((void));
  174. static void                     writeNACK PROTO((NINackPtr nackp));
  175. static NILoginPtr               readLOGIN PROTO ((void));
  176. static void                     writeLOGIN PROTO((NILoginPtr loginp));
  177. static NISvcListPtr             readSVC_LIST PROTO ((void));
  178. static void                     writeSVC_LIST PROTO((NISvcListPtr svclistp));
  179. static NISvcReqPtr              readSVC_REQUEST PROTO ((void));
  180. static void                     writeSVC_REQUEST PROTO((NISvcReqPtr svcreqp));
  181. static NISvcRespPtr             readSVC_RESPONSE PROTO ((void));
  182. static void                     writeSVC_RESPONSE PROTO((NISvcRespPtr svcrespp));
  183. static NICmdPtr                 readCOMMAND PROTO ((void));
  184. static void                     writeCOMMAND PROTO((NICmdPtr cmdp));
  185. static NIPreRespPtr             readPRE_RESPONSE PROTO ((void));
  186. static void                     writePRE_RESPONSE PROTO((NIPreRespPtr prp));
  187. static NIAcctPtr                readACCT PROTO ((void));
  188. static void                     writeACCT PROTO((NIAcctPtr accp));
  189. static NICatalogPtr             readCATALOG PROTO ((void));
  190. static void                     writeCATALOG PROTO((NICatalogPtr catp));
  191.  
  192. static int                      readRequest PROTO ((ReqPtr rp));
  193. static void                     writeRequest PROTO((ReqPtr reqp));
  194. static int                      readUid PROTO ((NI_UidPtr uid));
  195. static void                     writeUid PROTO((NI_UidPtr uidp));
  196. static int                      readService PROTO ((NISvcPtr svcp));
  197. static void                     writeService PROTO((NISvcPtr svcp));
  198. static int                      readResource PROTO ((NIResPtr resp));
  199. static void                     writeResource PROTO((NIResPtr resp));
  200. static int                      readRegion PROTO ((NIRegionPtr regp));
  201. static void                     writeRegion PROTO((NIRegionPtr regp));
  202. static int                      readToolset PROTO ((NIToolsetPtr tsp));
  203. static void                     writeToolset PROTO((NIToolsetPtr tsp));
  204. static int                      readPubKey PROTO ((NIPubKeyPtr pubkey));
  205. static void                     writePubKey PROTO((NIPubKeyPtr pubkey));
  206. static int                      readDispInfo PROTO ((NIDispInfoPtr dip));
  207. static void                     writeDispInfo PROTO((NIDispInfoPtr dip));
  208.  
  209. static Boolean                  InitMsg PROTO((void));
  210. static void                     WriteCleanup PROTO((CharPtr tmpbuf));
  211. static Boolean                  MsgHaveSavedData PROTO((MHandPtr mh));
  212. static void                     MsgSaveData PROTO((MHandPtr mh, CharPtr buf,
  213.                                                    Uint2 len));
  214. static int                      MsgReadSavedData PROTO((MHandPtr mh,
  215.                                                    CharPtr buf, Uint2 len));
  216. static void                     MsgFreeSavedData PROTO((MHandPtr mh));
  217. static void                     SetHourGlass PROTO((void));
  218. static void                     PopHourGlass PROTO((void));
  219.  
  220.  
  221. /* VARS */
  222.  
  223. Uint4           conid = 1;      /* globally unique connection ID counter */
  224. Jumpbuf         ni_env;         /* saved environment for LongJump (servers only) */
  225.  
  226. static AsnTypePtr       atp;
  227. static AsnIoPtr         aip;
  228.  
  229.  
  230.  
  231. /* FUNCTIONS */
  232.  
  233. /******************************************************************************/
  234. /*                                                                            */
  235. /* Functions for creating, destroying, reading, and writing message structures*/
  236. /*                                                                            */
  237. /******************************************************************************/
  238.  
  239.  
  240.  
  241.  
  242. /************************************ ACK *************************************/
  243.  
  244. NIAckPtr 
  245. NI_MakeMsgAck(void)
  246. {
  247.     NIAckPtr    ap;
  248.     
  249.     ap = (NIAckPtr) MemNew(sizeof(NIAck));
  250.     ap->seqno = 0;
  251.     ap->dispinfo = NULL;
  252.     ap->adminInfo = NULL;
  253.     ap->motd = NULL;
  254.     return ap;
  255. } /* NI_MakeMsgAck */
  256.  
  257.  
  258. Int2 
  259. NI_DestroyMsgAck(NIAckPtr mp)
  260. {
  261.     if (mp == NULL)
  262.         return 1;
  263.     if (mp->dispinfo != NULL)
  264.     {
  265.         NI_DestroyDispInfo(mp->dispinfo);
  266.     }
  267.     if (mp->adminInfo != NULL)
  268.     {
  269.         MemFree(mp->adminInfo);
  270.     }
  271.     if (mp->motd != NULL)
  272.     {
  273.         MemFree(mp->motd);
  274.     }
  275.     MemFree(mp);
  276.     return 0;
  277. } /* NI_MakeMsgAck */
  278.  
  279.  
  280. static NIAckPtr 
  281. readACK(void)
  282. {
  283.     DataVal     value;
  284.     NIAckPtr    ackp;
  285.     
  286.     ackp = NI_MakeMsgAck();
  287.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* seqno */
  288.         goto AckFail;
  289.     if (AsnReadVal(aip, atp, &value) < 0)
  290.         goto AckFail;
  291.     ackp->seqno = value.intvalue;
  292.     atp = AsnReadId(aip, amp, atp);
  293.     if (atp == MSG_ACK_disp_info) {
  294.         if (AsnReadVal(aip, atp, &value) < 0)
  295.             goto AckFail;
  296.         ackp->dispinfo = NI_MakeDispInfo();
  297.         if (readDispInfo(ackp->dispinfo) < 0)
  298.             goto AckFail;
  299.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  300.             goto AckFail;
  301.     }
  302.     if (atp == MSG_ACK_admin_info) {
  303.         if (AsnReadVal(aip, atp, &value) < 0)
  304.             goto AckFail;
  305.         ackp->adminInfo = (CharPtr) value.ptrvalue;
  306.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  307.             goto AckFail;
  308.     }
  309.     if (atp == MSG_ACK_motd) {
  310.         if (AsnReadVal(aip, atp, &value) < 0)
  311.             goto AckFail;
  312.         ackp->motd = (CharPtr) value.ptrvalue;
  313.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  314.             goto AckFail;
  315.     }
  316.     if (atp != MESSAGE_ack)
  317.         goto AckFail;
  318.     if (AsnReadVal(aip, atp, &value) < 0)
  319.         goto AckFail;
  320.     return ackp;
  321.  
  322.   AckFail:
  323.     NI_DestroyMsgAck(ackp);
  324.     return NULL;
  325. } /* readACK */
  326.  
  327.  
  328. static void 
  329. writeACK(NIAckPtr ackp)
  330. {
  331.     DataVal     value;
  332.  
  333.     AsnStartStruct(aip, MESSAGE_ack);
  334.     value.intvalue = (Int4) ackp->seqno;
  335.     AsnWrite(aip, MSG_ACK_seqno, &value);
  336.     if (ackp->dispinfo != NULL) {
  337.         AsnStartStruct(aip, MSG_ACK_disp_info);
  338.         writeDispInfo(ackp->dispinfo);
  339.         AsnEndStruct(aip, MSG_ACK_disp_info);
  340.     }
  341.     if (ackp->adminInfo != NULL) {
  342.         value.ptrvalue = (Pointer) ackp->adminInfo;
  343.         AsnWrite(aip, MSG_ACK_admin_info, &value);
  344.     }
  345.     if (ackp->motd != NULL) {
  346.         value.ptrvalue = (Pointer) ackp->motd;
  347.         AsnWrite(aip, MSG_ACK_motd, &value);
  348.     }
  349.  
  350.     AsnEndStruct(aip, MESSAGE_ack);
  351. } /* writeACK */
  352.  
  353.  
  354. /************************************ NACK ***********************************/
  355.  
  356. NINackPtr 
  357. NI_MakeMsgNack(void)
  358. {
  359.     NINackPtr   np;
  360.     
  361.     np = (NINackPtr) MemNew(sizeof(NINack));
  362.     np->seqno = 0;
  363.     np->reason = NULL;
  364.     np->dispinfo = NULL;
  365.     return np;
  366. } /* NI_MakeMsgNack */
  367.  
  368.  
  369. Int2 
  370. NI_DestroyMsgNack(NINackPtr mp)
  371. {
  372.     if (mp == NULL)
  373.         return 1;
  374.     if (mp->reason != NULL)
  375.         MemFree(mp->reason);
  376.     if (mp->dispinfo != NULL)
  377.         NI_DestroyDispInfo(mp->dispinfo);
  378.     MemFree(mp);
  379.     return 0;
  380. } /* NI_DestroyMsgNack */
  381.  
  382.  
  383. static NINackPtr 
  384. readNACK(void)
  385. {
  386.     DataVal     value;
  387.     NINackPtr   nackp;
  388.     
  389.     nackp = NI_MakeMsgNack();
  390.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* seqno */
  391.         goto NackFail;
  392.     if (AsnReadVal(aip, atp, &value) < 0)
  393.         goto NackFail;
  394.     nackp->seqno = value.intvalue;
  395.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* code */
  396.         goto NackFail;
  397.     if (AsnReadVal(aip, atp, &value) < 0)
  398.         goto NackFail;
  399.     nackp->code = (NI_Error) value.intvalue;
  400.     
  401.     if ((atp = AsnReadId(aip, amp, atp)) == MSG_NACK_reason) {  /* reason */
  402.         if (AsnReadVal(aip, atp, &value) < 0)
  403.             goto NackFail;
  404.         nackp->reason = (CharPtr) value.ptrvalue;
  405.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  406.             goto NackFail;
  407.     }
  408.     if (atp == MSG_NACK_disp_info) {
  409.         if (AsnReadVal(aip, atp, &value) < 0)
  410.             goto NackFail;
  411.         nackp->dispinfo = NI_MakeDispInfo();
  412.         if (readDispInfo(nackp->dispinfo) < 0)
  413.             goto NackFail;
  414.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  415.             goto NackFail;
  416.     }
  417.     if (atp != MESSAGE_nack)
  418.         goto NackFail;
  419.     if (AsnReadVal(aip, atp, &value) < 0)
  420.         goto NackFail;
  421.     return nackp;
  422.  
  423.   NackFail:
  424.     NI_DestroyMsgNack(nackp);
  425.     return NULL;
  426. } /* readNACK */
  427.  
  428.  
  429. static void 
  430. writeNACK(NINackPtr nackp)
  431. {
  432.     DataVal     value;
  433.  
  434.     AsnStartStruct(aip, MESSAGE_nack);
  435.     value.intvalue = (Int4) nackp->seqno;
  436.     AsnWrite(aip, MSG_NACK_seqno, &value);
  437.     value.intvalue = (Int4) nackp->code;
  438.     AsnWrite(aip, MSG_NACK_code, &value);
  439.     
  440.     if (nackp->reason != NULL) {
  441.         value.ptrvalue = (Pointer) nackp->reason;
  442.         AsnWrite(aip, MSG_NACK_reason, &value);
  443.     }
  444.     if (nackp->dispinfo != NULL) {
  445.         AsnStartStruct(aip, MSG_NACK_disp_info);
  446.         writeDispInfo(nackp->dispinfo);
  447.         AsnEndStruct(aip, MSG_NACK_disp_info);
  448.     }
  449.     AsnEndStruct(aip, MESSAGE_nack);
  450. }
  451.  
  452.  
  453. /************************************ LOGIN ***********************************/
  454.  
  455. NILoginPtr 
  456. NI_MakeMsgLogin(void)
  457. {
  458.     NILoginPtr  lp;
  459.     
  460.     lp = (NILoginPtr) MemNew(sizeof(NILogin));
  461.     lp->seqno = 0;
  462.     lp->uid = NI_MakeUid();
  463.     lp->password = NULL;
  464.     lp->dispserialno = -1;
  465.     lp->encryptionDesired = FALSE;
  466.     lp->pubKey = NULL;
  467.     lp->desKey = NULL;
  468.     lp->connectDelay = -1;
  469.     return lp;
  470. } /* NI_MakeMsgLogin() */
  471.  
  472.  
  473. Int2 
  474. NI_DestroyMsgLogin(NILoginPtr lp)
  475. {
  476.     if (lp == NULL)
  477.         return 1;
  478.     if (lp->uid != NULL)
  479.         NI_DestroyUid(lp->uid);
  480.     if (lp->password != NULL)
  481.         MemFree(lp->password);
  482.     if (lp->pubKey != NULL)
  483.         NI_DestroyPubKey(lp->pubKey);
  484.     if (lp->desKey != NULL)
  485.         BSFree(lp->desKey);
  486.     MemFree(lp);
  487.     return 0;
  488. } /* NI_DestroyMsgLogin() */
  489.  
  490.  
  491. static NILoginPtr 
  492. readLOGIN(void)
  493. {
  494.     DataVal     value;
  495.     NILoginPtr  loginp;
  496.     
  497.     loginp = NI_MakeMsgLogin();
  498.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* seqno */
  499.         goto LoginFail;
  500.     if (AsnReadVal(aip, atp, &value) < 0)
  501.         goto LoginFail;
  502.     loginp->seqno = value.intvalue;
  503.     
  504.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* MSG_LOGIN_uid */
  505.         goto LoginFail;
  506.     if (AsnReadVal(aip, atp, &value) < 0)
  507.         goto LoginFail;
  508.     if (readUid(loginp->uid) < 0)
  509.         goto LoginFail;
  510.     
  511.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* password ? */
  512.         goto LoginFail;
  513.  
  514.     if (atp == MSG_LOGIN_password) {
  515.         if (AsnReadVal(aip, atp, &value) < 0)
  516.             goto LoginFail;
  517.         loginp->password = (CharPtr) value.ptrvalue;
  518.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  519.             goto LoginFail;
  520.     }
  521.     
  522.     if (atp == MSG_LOGIN_disp_serial_no) {
  523.         if (AsnReadVal(aip, atp, &value) < 0)
  524.             goto LoginFail;
  525.         loginp->dispserialno = value.intvalue;
  526.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  527.             goto LoginFail;
  528.     }
  529.     
  530.     if (atp == MSG_LOGIN_encryption_desired) {
  531.         if (AsnReadVal(aip, atp, &value) < 0)
  532.             goto LoginFail;
  533.         loginp->encryptionDesired = value.boolvalue;
  534.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  535.             goto LoginFail;
  536.     }
  537.     
  538.     if (atp == MSG_LOGIN_pub_key) {
  539.         if (AsnReadVal(aip, atp, &value) < 0)
  540.             goto LoginFail;
  541.         loginp->pubKey = NI_MakePubKey();
  542.         if (readPubKey(loginp->pubKey) < 0)
  543.             goto LoginFail;
  544.         if ((atp = AsnReadId(aip,amp,atp)) == NULL)
  545.             goto LoginFail;
  546.     }
  547.     
  548.     if (atp == MSG_LOGIN_des_key) {
  549.         if (AsnReadVal(aip, atp, &value) < 0)
  550.             goto LoginFail;
  551.         loginp->desKey = (ByteStorePtr) value.ptrvalue;
  552.         if ((atp = AsnReadId(aip,amp,atp)) == NULL)
  553.             goto LoginFail;
  554.     }
  555.     
  556.     if (atp == MSG_LOGIN_connect_delay) {
  557.         if (AsnReadVal(aip, atp, &value) < 0)
  558.             goto LoginFail;
  559.         loginp->connectDelay = value.intvalue;
  560.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  561.             goto LoginFail;
  562.     }
  563.     
  564.     if (atp != MESSAGE_login)
  565.         goto LoginFail;
  566.     if (AsnReadVal(aip, atp, &value) < 0)
  567.         goto LoginFail;
  568.     return loginp;
  569.  
  570.   LoginFail:
  571.     NI_DestroyMsgLogin(loginp);
  572.     return NULL;
  573. } /* readLOGIN */
  574.  
  575.  
  576. static void 
  577. writeLOGIN(NILoginPtr loginp)
  578. {
  579.     DataVal     value;
  580.  
  581.     AsnStartStruct(aip, MESSAGE_login);
  582.     value.intvalue = (Int4) loginp->seqno;
  583.     AsnWrite(aip, MSG_LOGIN_seqno, &value);
  584.     AsnStartStruct(aip, MSG_LOGIN_uid);
  585.     writeUid(loginp->uid);
  586.     AsnEndStruct(aip, MSG_LOGIN_uid);
  587.     
  588.     if (loginp->password != NULL) {
  589.         value.ptrvalue = (Pointer) loginp->password;
  590.         AsnWrite(aip, MSG_LOGIN_password, &value);
  591.     }
  592.     if (loginp->dispserialno >= 0) {
  593.         value.intvalue = loginp->dispserialno;
  594.         AsnWrite(aip, MSG_LOGIN_disp_serial_no, &value);
  595.     }
  596.     if (loginp->encryptionDesired) {
  597.         value.boolvalue = loginp->encryptionDesired;
  598.         AsnWrite(aip, MSG_LOGIN_encryption_desired, &value);
  599.     }
  600.     if (loginp->pubKey != NULL) {
  601.         AsnStartStruct(aip, MSG_LOGIN_pub_key);
  602.         writePubKey(loginp->pubKey);
  603.         AsnEndStruct(aip, MSG_LOGIN_pub_key);
  604.     }
  605.     if (loginp->desKey != NULL) {
  606.         value.ptrvalue = (Pointer) loginp->desKey;
  607.         AsnWrite(aip, MSG_LOGIN_des_key, &value);
  608.     }
  609.     if (loginp->connectDelay >= 0) {
  610.         value.intvalue = loginp->connectDelay;
  611.         AsnWrite(aip, MSG_LOGIN_connect_delay, &value);
  612.     }
  613.     AsnEndStruct(aip, MESSAGE_login);
  614. } /* writeLOGIN */
  615.  
  616.  
  617. /************************************ SVC_LIST ********************************/
  618.  
  619. NISvcListPtr 
  620. NI_MakeMsgSvclist(void)
  621. {
  622.     NISvcListPtr        sp;
  623.     
  624.     sp = (NISvcListPtr) MemNew(sizeof(NISvcList));
  625.     sp->seqno = 0;
  626.     sp->toolset = NI_MakeToolset();
  627.     sp->knowsTracking = FALSE;
  628.     return sp;
  629. } /* NI_MakeMsgSvclist */
  630.  
  631.  
  632. Int2 
  633. NI_DestroyMsgSvclist(NISvcListPtr sp)
  634. {
  635.     if (sp == NULL)
  636.         return 1;
  637.     if (sp->toolset != NULL)
  638.         NI_DestroyToolset(sp->toolset);
  639.     MemFree(sp);
  640.     return 0;
  641. } /* NI_DestroyMsgSvclist */
  642.  
  643.  
  644. static NISvcListPtr 
  645. readSVC_LIST(void)
  646. {
  647.     DataVal     value;
  648.     NISvcListPtr        svclistp;
  649.     
  650.     svclistp = NI_MakeMsgSvclist();
  651.     
  652.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_SVC_LIST_seqno */
  653.         goto SvcListFail;
  654.     if (AsnReadVal(aip, atp, &value) < 0)
  655.         goto SvcListFail;
  656.     svclistp->seqno = value.intvalue;
  657.     
  658.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_SVC_LIST_toollist */
  659.         goto SvcListFail;
  660.     if (AsnReadVal(aip, atp, &value) < 0)
  661.         goto SvcListFail;
  662.     if (readToolset(svclistp->toolset) < 0)
  663.         goto SvcListFail;
  664.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  665.         goto SvcListFail;
  666.     if (AsnReadVal(aip, atp, &value) < 0)
  667.         goto SvcListFail;
  668.     
  669.     if (atp == MSG_SVC_LIST_knows_tracking)
  670.     {
  671.         svclistp->knowsTracking = value.boolvalue;
  672.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  673.             goto SvcListFail;
  674.         if (AsnReadVal(aip, atp, &value) < 0)
  675.             goto SvcListFail;
  676.     }
  677.  
  678.     if (atp != MESSAGE_svc_list)
  679.         goto SvcListFail;
  680.     return svclistp;
  681.  
  682.   SvcListFail:
  683.     NI_DestroyMsgSvclist(svclistp);
  684.     return NULL;
  685. } /* readSVC_LIST */
  686.  
  687.  
  688. static void 
  689. writeSVC_LIST(NISvcListPtr svclistp)
  690. {
  691.     DataVal     value;
  692.  
  693.     AsnStartStruct(aip, MESSAGE_svc_list);
  694.     value.intvalue = (Int4) svclistp->seqno;
  695.     AsnWrite(aip, MSG_SVC_LIST_seqno, &value);
  696.     
  697.     AsnStartStruct(aip, MSG_SVC_LIST_toollist);
  698.     writeToolset(svclistp->toolset);
  699.     AsnEndStruct(aip, MSG_SVC_LIST_toollist);
  700.     if (svclistp->knowsTracking)
  701.     {
  702.         value.boolvalue = svclistp->knowsTracking;
  703.         AsnWrite(aip, MSG_SVC_LIST_knows_tracking, &value);
  704.     }
  705.     
  706.     AsnEndStruct(aip, MESSAGE_svc_list);
  707. } /* writeSVC_LIST */
  708.  
  709.  
  710. /************************************ SVC_REQUEST *****************************/
  711.  
  712. NISvcReqPtr 
  713. NI_MakeMsgSvcreq(void)
  714. {
  715.     NISvcReqPtr sp;
  716.     
  717.     sp = (NISvcReqPtr) MemNew(sizeof(NISvcReq));
  718.     sp->seqno = 0;
  719.     sp->uid = NI_MakeUid();
  720.     sp->request = NI_MakeRequest();
  721.     sp->platform = NI_PLATFORM_UNKNOWN;
  722.     sp->applId = NULL;
  723.     sp->desKey = NULL;
  724.     sp->wantPreResponse = FALSE;
  725.     sp->server_ip = 0;
  726.     return sp;
  727. } /* NI_MakeMsgSvcreq() */
  728.  
  729.  
  730. Int2 
  731. NI_DestroyMsgSvcreq(NISvcReqPtr sp)
  732. {
  733.     if (sp == NULL)
  734.         return 1;
  735.     if (sp->uid != NULL)
  736.         NI_DestroyUid(sp->uid);
  737.     if (sp->request != NULL)
  738.         NI_DestroyRequest(sp->request);
  739.     if (sp->applId != NULL)
  740.         MemFree(sp->applId);
  741.     if (sp->desKey != NULL)
  742.         BSFree (sp->desKey);
  743.     MemFree(sp);
  744.     return 0;
  745. } /* NI_DestroyMsgSvcreq() */ 
  746.  
  747.  
  748. static NISvcReqPtr 
  749. readSVC_REQUEST(void)
  750. {
  751.     DataVal     value;
  752.     NISvcReqPtr svcreqp;
  753.     
  754.     svcreqp = NI_MakeMsgSvcreq();
  755.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* MSG_SVC_REQUEST_seqno */
  756.         goto SvcReqFail;
  757.     if (AsnReadVal(aip, atp, &value) < 0)
  758.         goto SvcReqFail;
  759.     svcreqp->seqno = value.intvalue;
  760.     
  761.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* MSG_SVC_REQUEST_conid */
  762.         goto SvcReqFail;
  763.     if (AsnReadVal(aip, atp, &value) < 0)
  764.         goto SvcReqFail;
  765.     svcreqp->conid = value.intvalue;
  766.     
  767.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* MSG_SVC_REQUEST_uid */
  768.         goto SvcReqFail;
  769.     if (AsnReadVal(aip, atp, &value) < 0)
  770.         goto SvcReqFail;
  771.     if (readUid(svcreqp->uid) < 0)
  772.         goto SvcReqFail;
  773.  
  774.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* MSG_SVC_REQUEST_request */
  775.         goto SvcReqFail;
  776.     if (AsnReadVal(aip, atp, &value) < 0)
  777.         goto SvcReqFail;
  778.     if (readRequest(svcreqp->request) < 0)
  779.         goto SvcReqFail;
  780.  
  781.     if ((atp = AsnReadId(aip, amp, atp)) == MSG_SVC_REQUEST_platform) {
  782.         if (AsnReadVal(aip, atp, &value) < 0)
  783.             goto SvcReqFail;
  784.         svcreqp->platform = (Uint4) value.intvalue;
  785.         atp = AsnReadId(aip, amp, atp);
  786.     }
  787.  
  788.     if (atp == MSG_SVC_REQUEST_appl_id) {
  789.         if (AsnReadVal(aip, atp, &value) < 0)
  790.             goto SvcReqFail;
  791.         svcreqp->applId = (CharPtr) value.ptrvalue;
  792.         atp = AsnReadId(aip, amp, atp);
  793.     }
  794.     
  795.     if (atp == MSG_SVC_REQUEST_des_key) {
  796.         if (AsnReadVal(aip, atp, &value) < 0)
  797.             goto SvcReqFail;
  798.         svcreqp->desKey = (ByteStorePtr) value.ptrvalue;
  799.         atp = AsnReadId(aip, amp, atp);
  800.     }
  801.  
  802.     if (atp == SVC_REQUEST_want_pre_response) {
  803.         if (AsnReadVal(aip, atp, &value) < 0)
  804.             goto SvcReqFail;
  805.         svcreqp->wantPreResponse = value.boolvalue;
  806.         atp = AsnReadId(aip, amp, atp);
  807.     }
  808.  
  809.     if (atp == MSG_SVC_REQUEST_server_ip) {
  810.         if (AsnReadVal(aip, atp, &value) < 0)
  811.             goto SvcReqFail;
  812.         svcreqp->server_ip = value.intvalue;
  813.         atp = AsnReadId(aip, amp, atp);
  814.     }
  815.  
  816.     if (atp != MESSAGE_svc_request)
  817.         goto SvcReqFail;
  818.     if (AsnReadVal(aip, atp, &value) < 0)
  819.         goto SvcReqFail;
  820.     return svcreqp;
  821.  
  822.   SvcReqFail:
  823.     NI_DestroyMsgSvcreq(svcreqp);
  824.     return NULL;
  825. } /* readSVC_REQUEST */
  826.  
  827.  
  828. static void 
  829. writeSVC_REQUEST(NISvcReqPtr svcreqp)
  830. {
  831.     DataVal     value;
  832.  
  833.     AsnStartStruct(aip, MESSAGE_svc_request);
  834.     value.intvalue = (Int4) svcreqp->seqno;
  835.     AsnWrite(aip, MSG_SVC_REQUEST_seqno, &value);
  836.     value.intvalue = (Int4) svcreqp->conid;
  837.     AsnWrite(aip, MSG_SVC_REQUEST_conid, &value);
  838.     AsnStartStruct(aip, MSG_SVC_REQUEST_uid);
  839.     writeUid(svcreqp->uid);
  840.     AsnEndStruct(aip, MSG_SVC_REQUEST_uid);
  841.     AsnStartStruct(aip, MSG_SVC_REQUEST_request);
  842.     writeRequest(svcreqp->request);
  843.     AsnEndStruct(aip, MSG_SVC_REQUEST_request);
  844.     value.intvalue = (Int4) svcreqp->platform;
  845.     AsnWrite(aip, MSG_SVC_REQUEST_platform, &value);
  846.  
  847.     if (svcreqp->applId != NULL)
  848.     {
  849.         value.ptrvalue = (Pointer) svcreqp->applId;
  850.         AsnWrite(aip, MSG_SVC_REQUEST_appl_id, &value);
  851.     }
  852.     
  853.     if (svcreqp->desKey != NULL)
  854.     {
  855.         value.ptrvalue = (Pointer) svcreqp->desKey;
  856.         AsnWrite(aip, MSG_SVC_REQUEST_des_key, &value);
  857.     }
  858.  
  859.     if (svcreqp->wantPreResponse)
  860.     {
  861.         value.boolvalue = svcreqp->wantPreResponse;
  862.         AsnWrite(aip, SVC_REQUEST_want_pre_response, &value);
  863.     }
  864.  
  865.     if (svcreqp->server_ip != 0)
  866.     {
  867.         value.intvalue = svcreqp->server_ip;
  868.         AsnWrite(aip, MSG_SVC_REQUEST_server_ip, &value);
  869.     }
  870.  
  871.     AsnEndStruct(aip, MESSAGE_svc_request);
  872. } /* writeSVC_REQUEST */
  873.  
  874.  
  875. /********************************* SVC_RESPONSE *******************************/
  876.  
  877. NISvcRespPtr 
  878. NI_MakeMsgSvcresp(void)
  879. {
  880.     NISvcRespPtr        sp;
  881.     
  882.     sp = (NISvcRespPtr) MemNew(sizeof(NISvcResp));
  883.     sp->seqno = 0;
  884.     sp->request = NI_MakeRequest();
  885.     return sp;
  886. } /* NI_MakeMsgSvcresp() */
  887.  
  888.  
  889. Int2 
  890. NI_DestroyMsgSvcresp(NISvcRespPtr sp)
  891. {
  892.     if (sp == NULL)
  893.         return 1;
  894.     if (sp->request != NULL)
  895.         NI_DestroyRequest(sp->request);
  896.     MemFree(sp);
  897.     return 0;
  898. } /* NI_DestroyMsgSvcresp() */ 
  899.  
  900.  
  901. static NISvcRespPtr 
  902. readSVC_RESPONSE(void)
  903. {
  904.     DataVal             value;
  905.     NISvcRespPtr        svcrespp;
  906.     
  907.     svcrespp = NI_MakeMsgSvcresp();
  908.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_SVC_RESPONSE_seqno */
  909.         goto SvcRespFail;
  910.     if (AsnReadVal(aip, atp, &value) < 0)
  911.         goto SvcRespFail;
  912.     svcrespp->seqno = value.intvalue;
  913.     
  914.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_SVC_RESPONSE_request */
  915.         goto SvcRespFail;
  916.     if (AsnReadVal(aip, atp, &value) < 0)
  917.         goto SvcRespFail;
  918.     if (readRequest(svcrespp->request) < 0)
  919.         goto SvcRespFail;
  920.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_SVC_RESPONSE_request */
  921.         goto SvcRespFail;
  922.     if (AsnReadVal(aip, atp, &value) < 0)
  923.         goto SvcRespFail;
  924.     
  925.     if (atp != MESSAGE_svc_response)
  926.         goto SvcRespFail;
  927.     return svcrespp;
  928.  
  929.   SvcRespFail:
  930.     NI_DestroyMsgSvcresp(svcrespp);
  931.     return NULL;
  932. } /* readSVC_RESPONSE */
  933.  
  934.  
  935. static void 
  936. writeSVC_RESPONSE(NISvcRespPtr svcrespp)
  937. {
  938.     DataVal     value;
  939.  
  940.     AsnStartStruct(aip, MESSAGE_svc_response);
  941.     value.intvalue = (Int4) svcrespp->seqno;
  942.     AsnWrite(aip, MSG_SVC_RESPONSE_seqno, &value);
  943.     AsnStartStruct(aip, MSG_SVC_RESPONSE_request);
  944.     writeRequest(svcrespp->request);
  945.     AsnEndStruct(aip, MSG_SVC_RESPONSE_request);
  946.     AsnEndStruct(aip, MESSAGE_svc_response);
  947. } /* writeSVC_RESPONSE */
  948.  
  949.  
  950. /************************************ COMMAND *********************************/
  951.  
  952. NICmdPtr 
  953. NI_MakeMsgCmd(void)
  954. {
  955.     NICmdPtr    cp;
  956.     
  957.     cp = (NICmdPtr) MemNew(sizeof(NICmd));
  958.     cp->seqno = 0;
  959.     return cp;
  960. } /* NI_MakeMsgCmd() */
  961.  
  962.  
  963. Int2 
  964. NI_DestroyMsgCmd(NICmdPtr cp)
  965. {
  966.     if (cp == NULL)
  967.         return 1;
  968.     MemFree(cp);
  969.     return 0;
  970. } /* NI_DestroyMsgCmd() */ 
  971.  
  972.  
  973. static NICmdPtr 
  974. readCOMMAND(void)
  975. {
  976.     DataVal     value;
  977.     NICmdPtr    cmdp;
  978.     
  979.     cmdp = NI_MakeMsgCmd();
  980.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* seqno */
  981.         goto CmdFail;
  982.     if (AsnReadVal(aip, atp, &value) < 0)
  983.         goto CmdFail;
  984.     cmdp->seqno = value.intvalue;
  985.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* command */
  986.         goto CmdFail;
  987.     if (AsnReadVal(aip, atp, &value) < 0)
  988.         goto CmdFail;
  989.     cmdp->code = (MsgCommand) value.intvalue;
  990.     if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE_command)
  991.         goto CmdFail;
  992.     if (AsnReadVal(aip, atp, &value) < 0)
  993.         goto CmdFail;
  994.     return cmdp;
  995.  
  996.   CmdFail:
  997.     NI_DestroyMsgCmd(cmdp);
  998.     return NULL;
  999. } /* readCOMMAND */
  1000.  
  1001.  
  1002. static void 
  1003. writeCOMMAND(NICmdPtr cmdp)
  1004. {
  1005.     DataVal     value;
  1006.  
  1007.     AsnStartStruct(aip, MESSAGE_command);
  1008.     value.intvalue = (Int4) cmdp->seqno;
  1009.     AsnWrite(aip, MSG_CMD_seqno, &value);
  1010.     value.intvalue = (Int4) cmdp->code;
  1011.     AsnWrite(aip, MSG_CMD_command, &value);
  1012.     AsnEndStruct(aip, MESSAGE_command);
  1013. } /* writeCOMMAND */
  1014.  
  1015.  
  1016. /************************************ PRE-RESPONSE *********************************/
  1017.  
  1018. NIPreRespPtr 
  1019. NI_MakeMsgPreResp(void)
  1020. {
  1021.     NIPreRespPtr    cp;
  1022.     
  1023.     cp = (NIPreRespPtr) MemNew(sizeof(NIPreResp));
  1024.     cp->seqno = 0;
  1025.     return cp;
  1026. } /* NI_MakeMsgPreResp() */
  1027.  
  1028.  
  1029. Int2 
  1030. NI_DestroyMsgPreResp(NIPreRespPtr cp)
  1031. {
  1032.     if (cp == NULL)
  1033.         return 1;
  1034.     MemFree(cp);
  1035.     return 0;
  1036. } /* NI_DestroyMsgPreResp() */ 
  1037.  
  1038.  
  1039. static NIPreRespPtr 
  1040. readPRE_RESPONSE(void)
  1041. {
  1042.     DataVal     value;
  1043.     NIPreRespPtr    prp;
  1044.     
  1045.     prp = NI_MakeMsgPreResp();
  1046.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* seqno */
  1047.         goto PrFail;
  1048.     if (AsnReadVal(aip, atp, &value) < 0)
  1049.         goto PrFail;
  1050.     prp->seqno = value.intvalue;
  1051.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* server IP */
  1052.         goto PrFail;
  1053.     if (AsnReadVal(aip, atp, &value) < 0)
  1054.         goto PrFail;
  1055.     prp->server_ip = value.intvalue;
  1056.     if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE_svc_pre_response)
  1057.         goto PrFail;
  1058.     if (AsnReadVal(aip, atp, &value) < 0)
  1059.         goto PrFail;
  1060.     return prp;
  1061.  
  1062.   PrFail:
  1063.     NI_DestroyMsgPreResp(prp);
  1064.     return NULL;
  1065. } /* readPRE_RESPONSE */
  1066.  
  1067.  
  1068. static void 
  1069. writePRE_RESPONSE(NIPreRespPtr prp)
  1070. {
  1071.     DataVal     value;
  1072.  
  1073.     AsnStartStruct(aip, MESSAGE_svc_pre_response);
  1074.     value.intvalue = (Int4) prp->seqno;
  1075.     AsnWrite(aip, MSG_SVC_PRE_RESPONSE_seqno, &value);
  1076.     value.intvalue = (Int4) prp->server_ip;
  1077.     AsnWrite(aip, MSG_SVC_PRE_RESPONSE_server_ip, &value);
  1078.     AsnEndStruct(aip, MESSAGE_svc_pre_response);
  1079. } /* writePRE_RESPONSE */
  1080.  
  1081. /************************************ ACCT ************************************/
  1082.  
  1083. NIAcctPtr 
  1084. NI_MakeMsgAcct(void)
  1085. {
  1086.     NIAcctPtr   ap;
  1087.     
  1088.     ap = (NIAcctPtr) MemNew(sizeof(NIAcct));
  1089.     ap->seqno = 0;
  1090.     ap->jobname = NULL;
  1091.     return ap;
  1092. } /* NI_MakeMsgAcct() */
  1093.  
  1094.  
  1095. Int2 
  1096. NI_DestroyMsgAcct(NIAcctPtr ap)
  1097. {
  1098.     if (ap == NULL)
  1099.         return 1;
  1100.     if (ap->jobname != NULL)
  1101.         MemFree(ap->jobname);
  1102.     MemFree(ap);
  1103.     return 0;
  1104. } /* NI_DestroyMsgAcct() */
  1105.  
  1106.  
  1107. static NIAcctPtr 
  1108. readACCT(void)
  1109. {
  1110.     DataVal     value;
  1111.     NIAcctPtr   accp;
  1112.     
  1113.     accp = NI_MakeMsgAcct();
  1114.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* seqno */
  1115.         goto AcctFail;
  1116.     if (AsnReadVal(aip, atp, &value) < 0)
  1117.         goto AcctFail;
  1118.     accp->seqno = value.intvalue;
  1119.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* conid */
  1120.         goto AcctFail;
  1121.     if (AsnReadVal(aip, atp, &value) < 0)
  1122.         goto AcctFail;
  1123.     accp->conid = value.intvalue;
  1124.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* jobname */
  1125.         goto AcctFail;
  1126.     if (AsnReadVal(aip, atp, &value) < 0)
  1127.         goto AcctFail;
  1128.     accp->jobname = (CharPtr) value.ptrvalue;
  1129.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* usertime */
  1130.         goto AcctFail;
  1131.     if (AsnReadVal(aip, atp, &value) < 0)
  1132.         goto AcctFail;
  1133.     accp->usertime = value.intvalue;
  1134.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* systemtime */
  1135.         goto AcctFail;
  1136.     if (AsnReadVal(aip, atp, &value) < 0)
  1137.         goto AcctFail;
  1138.     accp->systemtime = value.intvalue;
  1139.     if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE_acct)
  1140.         goto AcctFail;
  1141.     if (AsnReadVal(aip, atp, &value) < 0)
  1142.         goto AcctFail;
  1143.     return accp;
  1144.  
  1145.   AcctFail:
  1146.     NI_DestroyMsgAcct(accp);
  1147.     return NULL;
  1148. } /* NIreadACCT */
  1149.  
  1150.  
  1151. static void 
  1152. writeACCT(NIAcctPtr accp)
  1153. {
  1154.     DataVal     value;
  1155.  
  1156.     AsnStartStruct(aip, MESSAGE_acct);
  1157.     value.intvalue = (Int4) accp->seqno;
  1158.     AsnWrite(aip, MSG_ACCT_seqno, &value);
  1159.     value.intvalue = (Int4) accp->conid;
  1160.     AsnWrite(aip, MSG_ACCT_conid, &value);
  1161.     value.ptrvalue = (Pointer) accp->jobname;
  1162.     AsnWrite(aip, MSG_ACCT_jobname, &value);
  1163.     value.intvalue = (Int4) accp->usertime;
  1164.     AsnWrite(aip, MSG_ACCT_usertime, &value);
  1165.     value.intvalue = (Int4) accp->systemtime;
  1166.     AsnWrite(aip, MSG_ACCT_systemtime, &value);
  1167.     AsnEndStruct(aip, MESSAGE_acct);
  1168. } /* NIwriteACCT */
  1169.  
  1170.  
  1171. /************************************ CATALOG *********************************/
  1172.  
  1173. NICatalogPtr 
  1174. NI_MakeMsgCatalog(void)
  1175. {
  1176.     NICatalogPtr        cp;
  1177.     
  1178.     cp = (NICatalogPtr) MemNew(sizeof(NICatalog));
  1179.     cp->motd = NULL;
  1180.     cp->toolsetL = NULL;
  1181.     return cp;
  1182. } /* NI_MakeCatalog */
  1183.  
  1184.  
  1185. Int2 
  1186. NI_DestroyMsgCatalog(NICatalogPtr cp)
  1187. {
  1188.     NodePtr             np;
  1189.     
  1190.     
  1191.     if (cp == NULL)
  1192.         return 1;
  1193.     if (cp->motd != NULL)
  1194.         MemFree(cp->motd);
  1195.     if ((np = cp->toolsetL) != NULL) {
  1196.         do {
  1197.             NI_DestroyToolset((NIToolsetPtr) np->elem);
  1198.             np = ListDelete(np);
  1199.         } while (np != NULL);
  1200.     }   
  1201.     MemFree(cp);
  1202.     return 0;
  1203. } /* NI_DestroyMsgCatalog */
  1204.  
  1205.  
  1206. static NICatalogPtr 
  1207. readCATALOG(void)
  1208. {
  1209.     DataVal     value;
  1210.     NICatalogPtr        catp;
  1211.     NIToolsetPtr        tsp;
  1212.     
  1213.     catp = NI_MakeMsgCatalog();
  1214.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* MSG_CATALOG_seqno */
  1215.         goto CatalogFail;
  1216.     if (AsnReadVal(aip, atp, &value) < 0)
  1217.         goto CatalogFail;
  1218.     catp->seqno = value.intvalue;
  1219.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1220.         goto CatalogFail;
  1221.     
  1222.     if (atp == MSG_CATALOG_motd) {              /* MSG_CATALOG_motd ? */
  1223.         if (AsnReadVal(aip, atp, &value) < 0)
  1224.             goto CatalogFail;
  1225.         catp->motd = (CharPtr) value.ptrvalue;
  1226.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1227.             goto CatalogFail;
  1228.     }
  1229.     
  1230.     if (atp == MSG_CATALOG_toollists) {         /* MSG_CATALOG_toollists ? */
  1231.         if (AsnReadVal(aip, atp, &value) < 0)
  1232.             goto CatalogFail;
  1233.         while ((atp = AsnReadId(aip, amp, atp)) == MSG_CATALOG_toollists_E) {
  1234.             if (AsnReadVal(aip, atp, &value) < 0)
  1235.                 goto CatalogFail;
  1236.             tsp = NI_MakeToolset();
  1237.             if (readToolset(tsp) < 0)
  1238.                 goto CatalogFail;
  1239.             ListBreakRing(tsp->services);
  1240.             ListBreakRing(tsp->resources);
  1241.             catp->toolsetL = ListInsert((VoidPtr) tsp, catp->toolsetL); /* end of list */
  1242.         }
  1243.         if (atp == NULL)
  1244.             goto CatalogFail;
  1245.         catp->toolsetL = catp->toolsetL->next;          /* point to first */
  1246.         if (AsnReadVal(aip, atp, &value) < 0)           /* MSG_CATALOG_toollists */
  1247.             goto CatalogFail;
  1248.         ListBreakRing(catp->toolsetL);
  1249.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1250.             goto CatalogFail;
  1251.     }
  1252.     
  1253.     if (atp != MESSAGE_catalog)
  1254.         goto CatalogFail;
  1255.     if (AsnReadVal(aip, atp, &value) < 0)
  1256.         goto CatalogFail;
  1257.     return catp;
  1258.  
  1259.   CatalogFail:
  1260.     NI_DestroyMsgCatalog(catp);
  1261.     return NULL;
  1262. } /* readCATALOG */
  1263.  
  1264.  
  1265. static void 
  1266. writeCATALOG(NICatalogPtr catp)
  1267. {
  1268.     DataVal     value;
  1269.     NodePtr     np, lastnode;
  1270.     
  1271.     AsnStartStruct(aip, MESSAGE_catalog);
  1272.     value.intvalue = (Int4) catp->seqno;
  1273.     AsnWrite(aip, MSG_CATALOG_seqno, &value);
  1274.     if (catp->motd != NULL) {
  1275.         value.ptrvalue = (Pointer) catp->motd;
  1276.         AsnWrite(aip, MSG_CATALOG_motd, &value);
  1277.     }
  1278.     
  1279.     np = catp->toolsetL;
  1280.     if (np != NULL) {
  1281.         AsnStartStruct(aip, MSG_CATALOG_toollists);
  1282.         lastnode = np->last;
  1283.         while (np != NULL) {
  1284.             AsnStartStruct(aip, MSG_CATALOG_toollists_E);
  1285.             writeToolset((NIToolsetPtr) np->elem);
  1286.             AsnEndStruct(aip, MSG_CATALOG_toollists_E);
  1287.             if (np == lastnode)
  1288.                 break;
  1289.             np = np->next;
  1290.         }
  1291.         AsnEndStruct(aip, MSG_CATALOG_toollists);
  1292.     }
  1293.     
  1294.     AsnEndStruct(aip, MESSAGE_catalog);
  1295. } /* writeCatalog */
  1296.  
  1297.  
  1298. /************************************ REQUEST *********************************/
  1299.  
  1300. ReqPtr
  1301. NI_MakeRequest(void)
  1302. {
  1303.     ReqPtr              rp;
  1304.     
  1305.     rp = (ReqPtr) MemNew(sizeof(Request));
  1306.     rp->clientAddr = NULL;
  1307.     rp->clientPort = 0;
  1308.     rp->service = NI_MakeService();
  1309.     rp->resourceL = NULL;
  1310.     return(rp);
  1311. } /* NI_MakeRequest() */
  1312.  
  1313.  
  1314. Int2
  1315. NI_DestroyRequest(ReqPtr rp)
  1316. {
  1317.     if (rp == NULL)
  1318.         return 1;
  1319.     if (rp->clientAddr != NULL)
  1320.         MemFree(rp->clientAddr);
  1321.     if (rp->service != NULL)
  1322.         NI_DestroyService(rp->service);
  1323.     if (rp->resourceL != NULL) {        /* destroy list of nodes and resources they point to */
  1324.         while (rp->resourceL != NULL) {
  1325.             NI_DestroyResource((NIResPtr)rp->resourceL->elem);
  1326.             rp->resourceL = ListDelete(rp->resourceL);
  1327.         }
  1328.     }
  1329.     MemFree(rp);
  1330.     return 0;
  1331. } /* NI_DestroyRequest() */
  1332.  
  1333.  
  1334. static int
  1335. readRequest(ReqPtr reqp)
  1336. {
  1337.     DataVal     value;
  1338.     NIResPtr    resp;
  1339.     
  1340.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1341.         goto RequestFail;
  1342.     if (atp == REQUEST_address) {               /* REQUEST_address ? */
  1343.         if (AsnReadVal(aip, atp, &value) < 0)
  1344.             goto RequestFail;
  1345.         reqp->clientAddr = (CharPtr) value.ptrvalue;
  1346.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1347.             goto RequestFail;
  1348.     }
  1349.     if (atp == REQUEST_port) {                  /* REQUEST_port ? */
  1350.         if (AsnReadVal(aip, atp, &value) < 0)
  1351.             goto RequestFail;
  1352.         reqp->clientPort = (Uint2) value.intvalue;
  1353.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1354.             goto RequestFail;
  1355.     }
  1356.     if (AsnReadVal(aip, atp, &value) < 0)       /* REQUEST_svcentry */
  1357.         goto RequestFail;
  1358.     if (readService(reqp->service) < 0)
  1359.         goto RequestFail;
  1360.     
  1361.     if ((atp = AsnReadId(aip, amp, atp)) == REQUEST_resentry) {
  1362.         if (AsnReadVal(aip, atp, &value) < 0)
  1363.             goto RequestFail;
  1364.  
  1365.         while ((atp = AsnReadId(aip, amp, atp)) == REQUEST_resentry_E) {
  1366.             if (AsnReadVal(aip, atp, &value) < 0)
  1367.                 goto RequestFail;
  1368.             resp = NI_MakeResource();
  1369.             if (readResource(resp) < 0) {
  1370.                 NI_DestroyResource(resp);
  1371.                 goto RequestFail;
  1372.             }
  1373.             reqp->resourceL = ListInsert((VoidPtr) resp, reqp->resourceL);      /* end of list */
  1374.         }
  1375.         if (atp == NULL)
  1376.             goto RequestFail;
  1377.         reqp->resourceL = reqp->resourceL->next;        /* point to first */
  1378.         if (AsnReadVal(aip, atp, &value) < 0)           /* REQUEST_resentry */
  1379.             goto RequestFail;
  1380.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1381.             goto RequestFail;
  1382.     }
  1383.     if (atp == NULL)
  1384.         goto RequestFail;
  1385.  
  1386.     if (AsnReadVal(aip, atp, &value) < 0)
  1387.         goto RequestFail;
  1388.     return 0;
  1389.  
  1390.   RequestFail:
  1391.     if (reqp->resourceL != NULL) {      /* destroy list of nodes and resources they point to */
  1392.         while (reqp->resourceL != NULL) {
  1393.             NI_DestroyResource((NIResPtr)reqp->resourceL->elem);
  1394.             reqp->resourceL = ListDelete(reqp->resourceL);
  1395.         }
  1396.     }
  1397.     return -1;
  1398. } /* readrequest */
  1399.  
  1400.  
  1401. static void 
  1402. writeRequest(ReqPtr reqp)
  1403. {
  1404.     DataVal     value;
  1405.     NodePtr     np, lastnode;
  1406.     
  1407.     if (reqp->clientAddr != NULL) {
  1408.         value.ptrvalue = (Pointer) reqp->clientAddr;
  1409.         AsnWrite(aip, REQUEST_address, &value);
  1410.     }
  1411.     if (reqp->clientPort != 0) {
  1412.         value.intvalue = (Int4) reqp->clientPort;
  1413.         AsnWrite(aip, REQUEST_port, &value);
  1414.     }
  1415.     AsnStartStruct(aip, REQUEST_svcentry);
  1416.     writeService(reqp->service);
  1417.     AsnEndStruct(aip, REQUEST_svcentry);
  1418.     
  1419.     np = reqp->resourceL;
  1420.     if (np != NULL) {
  1421.         AsnStartStruct(aip, REQUEST_resentry);
  1422.         lastnode = np->last;
  1423.         while (np != NULL) {
  1424.             AsnStartStruct(aip, REQUEST_resentry_E);
  1425.             writeResource((NIResPtr) np->elem);
  1426.             AsnEndStruct(aip, REQUEST_resentry_E);
  1427.             if (np == lastnode)
  1428.                 break;
  1429.             np = np->next;
  1430.         }
  1431.         AsnEndStruct(aip, REQUEST_resentry);
  1432.     }
  1433. } /* writeRequest */
  1434.  
  1435.  
  1436. /************************************ UID *************************************/
  1437.  
  1438. NI_UidPtr 
  1439. NI_MakeUid(void)
  1440. {
  1441.     NI_UidPtr   up;
  1442.     
  1443.     up = (NI_UidPtr) MemNew(sizeof(NI_Uid));
  1444.     up->username = NULL;
  1445.     up->group = NULL;
  1446.     up->domain = NULL;
  1447.     return up;
  1448. } /* NI_MakeUid */
  1449.  
  1450.  
  1451. Int2 
  1452. NI_DestroyUid(NI_UidPtr up)
  1453. {
  1454.     if (up == NULL)
  1455.         return 1;
  1456.     if (up->username != NULL)
  1457.         MemFree(up->username);
  1458.     if (up->group != NULL)
  1459.         MemFree(up->group);
  1460.     if (up->domain != NULL)
  1461.         MemFree(up->domain);
  1462.     MemFree(up);
  1463.     return 0;
  1464. } /* NI_DestroyUid */
  1465.  
  1466.  
  1467. static int 
  1468. readUid(NI_UidPtr uidptr)
  1469. {
  1470.     DataVal     value;
  1471.  
  1472.     if ((atp = AsnReadId(aip, amp, atp)) == NULL || atp != IDENTITY_username)           /* username */
  1473.         goto UidFail;
  1474.     if (AsnReadVal(aip, atp, &value) < 0)
  1475.         goto UidFail;
  1476.     uidptr->username = (CharPtr) value.ptrvalue;
  1477.     
  1478.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* group ? */
  1479.         goto UidFail;
  1480.     if (atp == IDENTITY_group) {
  1481.         if (AsnReadVal(aip, atp, &value) < 0)
  1482.             goto UidFail;
  1483.         uidptr->group = (CharPtr) value.ptrvalue;
  1484.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)           /* domain ? */
  1485.             goto UidFail;
  1486.     }
  1487.     if (atp == IDENTITY_domain) {
  1488.         if (AsnReadVal(aip, atp, &value) < 0)
  1489.             goto UidFail;
  1490.         uidptr->domain = (CharPtr) value.ptrvalue;
  1491.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1492.             goto UidFail;
  1493.     }
  1494.     if (AsnReadVal(aip, atp, &value) < 0)
  1495.         goto UidFail;
  1496.     return 0;
  1497.  
  1498.   UidFail:
  1499.     return -1;
  1500. } /* readUid */
  1501.  
  1502.  
  1503. static void 
  1504. writeUid(NI_UidPtr uidptr)
  1505. {
  1506.     DataVal     value;
  1507.     
  1508.     value.ptrvalue = (Pointer) uidptr->username;
  1509.     AsnWrite(aip, IDENTITY_username, &value);
  1510.     
  1511.     if (uidptr->group != NULL) {
  1512.         value.ptrvalue = (Pointer) uidptr->group;
  1513.         AsnWrite(aip, IDENTITY_group, &value);
  1514.     }
  1515.     if (uidptr->domain != NULL) {
  1516.         value.ptrvalue = (Pointer) uidptr->domain;
  1517.         AsnWrite(aip, IDENTITY_domain, &value);
  1518.     }
  1519. } /* writeUid */
  1520.  
  1521.  
  1522. /************************************ SERVICE *********************************/
  1523.  
  1524. NISvcPtr 
  1525. NI_MakeService(void)
  1526. {
  1527.     NISvcPtr    sp;
  1528.     
  1529.     sp = (NISvcPtr) MemNew(sizeof(NIService));
  1530.     sp->name = NULL;
  1531.     sp->minVersion = 0;
  1532.     sp->maxVersion = 0;
  1533.     sp->id = 0;
  1534.     sp->priority = 0;
  1535.     sp->priorityTimeout = 0;
  1536.     sp->priorityPenalty = 0;
  1537.     sp->group = NULL;
  1538.     sp->descrip = NULL;
  1539.     sp->typeL = NULL;
  1540.     sp->encryptionSupported = FALSE;
  1541.     sp->trackingPeriod = 0;
  1542.     sp->trackingCount = 0;
  1543.     return sp;
  1544. } /* NI_MakeService() */
  1545.  
  1546.  
  1547. Int2 
  1548. NI_DestroyService(NISvcPtr sp)
  1549. {
  1550.     if (sp == NULL)
  1551.         return 1;
  1552.     if (sp->name != NULL)
  1553.         MemFree(sp->name);
  1554.     if (sp->group != NULL)
  1555.         MemFree(sp->group);
  1556.     if (sp->descrip != NULL)
  1557.         MemFree(sp->descrip);
  1558.     if (sp->typeL != NULL) { /* destroy list of service types */
  1559.         ListStrDel(sp->typeL);
  1560.     }
  1561.     if (sp->subSetList != NULL) {
  1562.         ListStrDel(sp->subSetList);
  1563.     }
  1564.     if (sp->superSetList != NULL) {
  1565.         ListStrDel(sp->superSetList);
  1566.     }
  1567.  
  1568.     MemFree(sp);
  1569.     return 0;
  1570. } /* NI_DestroyService() */
  1571.  
  1572.  
  1573. static int 
  1574. readService(NISvcPtr svcptr)
  1575. {
  1576.     DataVal     value;
  1577.     CharPtr     svctype;
  1578.  
  1579.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* SVC_ENTRY_name */
  1580.         goto ServiceFail;
  1581.     if (AsnReadVal(aip, atp, &value) < 0)
  1582.         goto ServiceFail;
  1583.     svcptr->name = (CharPtr) value.ptrvalue;
  1584.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* SVC_ENTRY_minvers */
  1585.         goto ServiceFail;
  1586.     if (AsnReadVal(aip, atp, &value) < 0)
  1587.         goto ServiceFail;
  1588.     svcptr->minVersion = (Uint2) value.intvalue;
  1589.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* SVC_ENTRY_maxvers */
  1590.         goto ServiceFail;
  1591.     if (AsnReadVal(aip, atp, &value) < 0)
  1592.         goto ServiceFail;
  1593.     svcptr->maxVersion = (Uint2) value.intvalue;
  1594.     
  1595.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1596.         goto ServiceFail;
  1597.     if (atp == SVC_ENTRY_id) {                          /* SVC_ENTRY_id ? */
  1598.         if (AsnReadVal(aip, atp, &value) < 0)
  1599.             goto ServiceFail;
  1600.         svcptr->id = (Uint2) value.intvalue;
  1601.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1602.             goto ServiceFail;
  1603.     }
  1604.     if (atp == SVC_ENTRY_priority) {                    /* SVC_ENTRY_priority ? */
  1605.         if (AsnReadVal(aip, atp, &value) < 0)
  1606.             goto ServiceFail;
  1607.         svcptr->priority = (Uint2) value.intvalue;
  1608.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1609.             goto ServiceFail;
  1610.     }
  1611.     if (atp == SVC_ENTRY_group) {                       /* SVC_ENTRY_group ? */
  1612.         if (AsnReadVal(aip, atp, &value) < 0)
  1613.             goto ServiceFail;
  1614.         svcptr->group = (CharPtr) value.ptrvalue;
  1615.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1616.             goto ServiceFail;
  1617.     }
  1618.     if (atp == SVC_ENTRY_description) {                 /* SVC_ENTRY_description ? */
  1619.         if (AsnReadVal(aip, atp, &value) < 0)
  1620.             goto ServiceFail;
  1621.         svcptr->descrip = (CharPtr) value.ptrvalue;
  1622.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1623.             goto ServiceFail;
  1624.     }
  1625.     if (atp == SVC_ENTRY_types) {
  1626.         if (AsnReadVal(aip, atp, &value) < 0)
  1627.             goto ServiceFail;
  1628.  
  1629.         /* read the list of service types */
  1630.         while ((atp = AsnReadId(aip, amp, atp)) == SVC_ENTRY_types_E)
  1631.         {
  1632.             if (AsnReadVal(aip, atp, &value) < 0)
  1633.                 goto ServiceFail;
  1634.             svctype = value.ptrvalue;
  1635.             svcptr->typeL = ListInsert((VoidPtr) svctype, svcptr->typeL);
  1636.         }
  1637.         if (atp == NULL)
  1638.             goto ServiceFail;
  1639.         svcptr->typeL = svcptr->typeL->next;            /* point to first */
  1640.         if (AsnReadVal(aip, atp, &value) < 0)           /* SVC_ENTRY_types */
  1641.             goto ServiceFail;
  1642.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1643.             goto ServiceFail;
  1644.     }
  1645.  
  1646.     if (atp == SVC_ENTRY_priority_timeout) {
  1647.         if (AsnReadVal(aip, atp, &value) < 0)
  1648.             goto ServiceFail;
  1649.         svcptr->priorityTimeout = (Uint2) value.intvalue;
  1650.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1651.             goto ServiceFail;
  1652.     }
  1653.  
  1654.     if (atp == SVC_ENTRY_priority_penalty) {
  1655.         if (AsnReadVal(aip, atp, &value) < 0)
  1656.             goto ServiceFail;
  1657.         svcptr->priorityPenalty = (Uint2) value.intvalue;
  1658.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1659.             goto ServiceFail;
  1660.     }
  1661.     
  1662.     if (atp == SVC_ENTRY_encryption_supported) {
  1663.         if (AsnReadVal(aip, atp, &value) < 0)
  1664.             goto ServiceFail;
  1665.         svcptr->encryptionSupported = value.boolvalue;
  1666.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1667.             goto ServiceFail;
  1668.     }
  1669.         
  1670.     if (atp == SVC_ENTRY_tracking_period) {
  1671.         if (AsnReadVal(aip, atp, &value) < 0)
  1672.             goto ServiceFail;
  1673.         svcptr->trackingPeriod = value.intvalue;
  1674.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1675.             goto ServiceFail;
  1676.     }
  1677.         
  1678.     if (atp == SVC_ENTRY_tracking_count) {
  1679.         if (AsnReadVal(aip, atp, &value) < 0)
  1680.             goto ServiceFail;
  1681.         svcptr->trackingCount = value.intvalue;
  1682.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1683.             goto ServiceFail;
  1684.     }
  1685.         
  1686.     if (atp == NULL)
  1687.         goto ServiceFail;
  1688.  
  1689.     if (AsnReadVal(aip, atp, &value) < 0)
  1690.         goto ServiceFail;
  1691.     return 0;
  1692.  
  1693.   ServiceFail:
  1694.     return -1;
  1695. } /* readService */
  1696.  
  1697.  
  1698. static void 
  1699. writeService(NISvcPtr svcptr)
  1700. {
  1701.     DataVal     value;
  1702.     NodePtr     np;
  1703.     NodePtr     lastnode;
  1704.  
  1705.     value.ptrvalue = (Pointer) svcptr->name;
  1706.     AsnWrite(aip, SVC_ENTRY_name, &value);
  1707.     value.intvalue = (Int4) svcptr->minVersion;
  1708.     AsnWrite(aip, SVC_ENTRY_minvers, &value);
  1709.     value.intvalue = (Int4) svcptr->maxVersion;
  1710.     AsnWrite(aip, SVC_ENTRY_maxvers, &value);
  1711.     
  1712.     if (svcptr->id != 0) {
  1713.         value.intvalue = (Int4) svcptr->id;
  1714.         AsnWrite(aip, SVC_ENTRY_id, &value);
  1715.     }
  1716.     if (svcptr->priority != 0) {
  1717.         value.intvalue = (Int4) svcptr->priority;
  1718.         AsnWrite(aip, SVC_ENTRY_priority, &value);
  1719.     }
  1720.     if (svcptr->group != NULL) {
  1721.         value.ptrvalue = (Pointer) svcptr->group;
  1722.         AsnWrite(aip, SVC_ENTRY_group, &value);
  1723.     }
  1724.     if (svcptr->descrip != NULL) {
  1725.         value.ptrvalue = (Pointer) svcptr->descrip;
  1726.         AsnWrite(aip, SVC_ENTRY_description, &value);
  1727.     }
  1728.  
  1729.     np = svcptr->typeL;
  1730.     if (np != NULL) {
  1731.         AsnStartStruct(aip, SVC_ENTRY_types);
  1732.         lastnode = np->last;
  1733.         while (np != NULL) {
  1734.             value.ptrvalue = (Pointer) np->elem;
  1735.             AsnWrite(aip, SVC_ENTRY_types_E, &value);
  1736.             if (np == lastnode)
  1737.                 break;
  1738.             np = np->next;
  1739.         }
  1740.         AsnEndStruct(aip, SVC_ENTRY_types);
  1741.     }
  1742.  
  1743.     if (svcptr->priorityTimeout != 0)
  1744.     {
  1745.         value.intvalue = svcptr->priorityTimeout;
  1746.         AsnWrite(aip, SVC_ENTRY_priority_timeout, &value);
  1747.     }
  1748.  
  1749.     if (svcptr->priorityPenalty != 0)
  1750.     {
  1751.         value.intvalue = svcptr->priorityPenalty;
  1752.         AsnWrite(aip, SVC_ENTRY_priority_penalty, &value);
  1753.     }
  1754.  
  1755.     if (svcptr->encryptionSupported)
  1756.     {
  1757.         value.boolvalue = svcptr->encryptionSupported;
  1758.         AsnWrite(aip, SVC_ENTRY_encryption_supported, &value);
  1759.     }
  1760.  
  1761.     if (svcptr->trackingPeriod != 0)
  1762.     {
  1763.         value.intvalue = svcptr->trackingPeriod;
  1764.         AsnWrite(aip, SVC_ENTRY_tracking_period, &value);
  1765.     }
  1766.  
  1767.     if (svcptr->trackingCount != 0)
  1768.     {
  1769.         value.intvalue = svcptr->trackingCount;
  1770.         AsnWrite(aip, SVC_ENTRY_tracking_count, &value);
  1771.     }
  1772. } /* writeService */
  1773.  
  1774.  
  1775. /************************************ RESOURCE ********************************/
  1776.  
  1777. NIResPtr 
  1778. NI_MakeResource(void)
  1779. {
  1780.     NIResPtr    rp;
  1781.     
  1782.     rp = (NIResPtr) MemNew(sizeof(NIResource));
  1783.     rp->name = NULL;
  1784.     rp->type = NULL;
  1785.     rp->minVersion = 0;
  1786.     rp->maxVersion = 0;
  1787.     rp->id = 0;
  1788.     rp->group = NULL;
  1789.     rp->descrip = NULL;
  1790.     return rp;
  1791. } /* NI_MakeResource() */
  1792.  
  1793.  
  1794. Int2 
  1795. NI_DestroyResource(NIResPtr rp)
  1796. {
  1797.     if (rp == NULL)
  1798.         return 1;
  1799.     if (rp->name != NULL)
  1800.         MemFree(rp->name);
  1801.     if (rp->type != NULL)
  1802.         MemFree(rp->type);
  1803.     if (rp->group != NULL)
  1804.         MemFree(rp->group);
  1805.     if (rp->descrip != NULL)
  1806.         MemFree(rp->descrip);
  1807.     MemFree(rp);
  1808.     return 0;
  1809. } /* NI_DestroyResource */
  1810.  
  1811.  
  1812. static int
  1813. readResource(NIResPtr resptr)
  1814. {
  1815.     DataVal     value;
  1816.  
  1817.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* RES_ENTRY_name */
  1818.         goto ResourceFail;
  1819.     if (AsnReadVal(aip, atp, &value) < 0)
  1820.         goto ResourceFail;
  1821.     resptr->name = (CharPtr) value.ptrvalue;
  1822.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* RES_ENTRY_type */
  1823.         goto ResourceFail;
  1824.     if (AsnReadVal(aip, atp, &value) < 0)
  1825.         goto ResourceFail;
  1826.     resptr->type = (CharPtr) value.ptrvalue;
  1827.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* RES_ENTRY_minvers */
  1828.         goto ResourceFail;
  1829.     if (AsnReadVal(aip, atp, &value) < 0)
  1830.         goto ResourceFail;
  1831.     resptr->minVersion = (Uint2) value.intvalue;
  1832.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* RES_ENTRY_maxvers */
  1833.         goto ResourceFail;
  1834.     if (AsnReadVal(aip, atp, &value) < 0)
  1835.         goto ResourceFail;
  1836.     resptr->maxVersion = (Uint2) value.intvalue;
  1837.     
  1838.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1839.         goto ResourceFail;
  1840.     if (atp == RES_ENTRY_id) {                          /* RES_ENTRY_id */
  1841.         if (AsnReadVal(aip, atp, &value) < 0)
  1842.             goto ResourceFail;
  1843.         resptr->id = (Uint2) value.intvalue;
  1844.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1845.             goto ResourceFail;
  1846.     }
  1847.     if (atp == RES_ENTRY_group) {                       /* RES_ENTRY_group */
  1848.         if (AsnReadVal(aip, atp, &value) < 0)
  1849.             goto ResourceFail;
  1850.         resptr->group = (CharPtr) value.ptrvalue;
  1851.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1852.             goto ResourceFail;
  1853.     }
  1854.     if (atp == RES_ENTRY_description) {                 /* RES_ENTRY_description */
  1855.         if (AsnReadVal(aip, atp, &value) < 0)
  1856.             goto ResourceFail;
  1857.         resptr->descrip = (CharPtr) value.ptrvalue;
  1858.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1859.             goto ResourceFail;
  1860.     }
  1861.     if (AsnReadVal(aip, atp, &value) < 0)
  1862.         goto ResourceFail;
  1863.     return 0;
  1864.  
  1865.   ResourceFail:
  1866.     return -1;
  1867. } /* readResource */
  1868.  
  1869.  
  1870. static void 
  1871. writeResource(NIResPtr resptr)
  1872. {
  1873.     DataVal     value;
  1874.  
  1875.     value.ptrvalue = (Pointer) resptr->name;
  1876.     AsnWrite(aip, RES_ENTRY_name, &value);
  1877.     value.ptrvalue = (Pointer) resptr->type;
  1878.     AsnWrite(aip, RES_ENTRY_type, &value);
  1879.     value.intvalue = (Int4) resptr->minVersion;
  1880.     AsnWrite(aip, RES_ENTRY_minvers, &value);
  1881.     value.intvalue = (Int4) resptr->maxVersion;
  1882.     AsnWrite(aip, RES_ENTRY_maxvers, &value);
  1883.     
  1884.     if (resptr->id != 0) {
  1885.         value.intvalue = (Int4) resptr->id;
  1886.         AsnWrite(aip, RES_ENTRY_id, &value);
  1887.     }
  1888.     if (resptr->group != NULL) {
  1889.         value.ptrvalue = (Pointer) resptr->group;
  1890.         AsnWrite(aip, RES_ENTRY_group, &value);
  1891.     }
  1892.     if (resptr->descrip != NULL) {
  1893.         value.ptrvalue = (Pointer) resptr->descrip;
  1894.         AsnWrite(aip, RES_ENTRY_description, &value);
  1895.     }
  1896. } /* writeResource */
  1897.  
  1898.  
  1899. /************************************ REGION *********************************/
  1900.  
  1901. NIRegionPtr 
  1902. NI_MakeRegion(void)
  1903. {
  1904.     NIRegionPtr    rp;
  1905.     
  1906.     rp = (NIRegionPtr) MemNew(sizeof(NIRegion));
  1907.     rp->regionName = NULL;
  1908.     rp->priorityDelta = 0;
  1909.     return rp;
  1910. } /* NI_MakeRegion() */
  1911.  
  1912.  
  1913. Int2 
  1914. NI_DestroyRegion(NIRegionPtr rp)
  1915. {
  1916.     if (rp == NULL)
  1917.         return 1;
  1918.     if (rp->regionName != NULL)
  1919.         MemFree(rp->regionName);
  1920.  
  1921.     MemFree(rp);
  1922.     return 0;
  1923. } /* NI_DestroyRegion() */
  1924.  
  1925.  
  1926. static int 
  1927. readRegion(NIRegionPtr regptr)
  1928. {
  1929.     DataVal     value;
  1930.  
  1931.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* REGION_DESCR_region_name */
  1932.         goto RegionFail;
  1933.     if (AsnReadVal(aip, atp, &value) < 0)
  1934.         goto RegionFail;
  1935.     regptr->regionName = (CharPtr) value.ptrvalue;
  1936.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* REGION_DESCR_priority_delta */
  1937.         goto RegionFail;
  1938.     if (AsnReadVal(aip, atp, &value) < 0)
  1939.         goto RegionFail;
  1940.     regptr->priorityDelta = (Uint2) value.intvalue;
  1941.  
  1942.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  1943.         goto RegionFail;
  1944.  
  1945.     if (AsnReadVal(aip, atp, &value) < 0)
  1946.         goto RegionFail;
  1947.     return 0;
  1948.  
  1949.   RegionFail:
  1950.     return -1;
  1951. } /* readRegion */
  1952.  
  1953.  
  1954. static void 
  1955. writeRegion(NIRegionPtr regptr)
  1956. {
  1957.     DataVal     value;
  1958.  
  1959.     value.ptrvalue = (Pointer) regptr->regionName;
  1960.     AsnWrite(aip, REGION_DESCR_region_name, &value);
  1961.     value.intvalue = (Int4) regptr->priorityDelta;
  1962.     AsnWrite(aip, REGION_DESCR_priority_delta, &value);
  1963. } /* writeRegion */
  1964.  
  1965.  
  1966.  
  1967. /************************************ PubKey ********************************/
  1968.  
  1969. NIPubKeyPtr
  1970. NI_MakePubKey(void)
  1971. {
  1972.     NIPubKeyPtr pubkey;
  1973.  
  1974.     pubkey = (NIPubKeyPtr) MemNew(sizeof(NIPubKey));
  1975.     pubkey->bits = 0;
  1976.     pubkey->modulus = NULL;
  1977.     pubkey->exponent = NULL;
  1978.     return pubkey;
  1979. } /* NI_MakePubKey */
  1980.  
  1981.  
  1982. Int2
  1983. NI_DestroyPubKey(NIPubKeyPtr pubkey)
  1984. {
  1985.     if (pubkey == NULL)
  1986.         return 1;
  1987.     if (pubkey->modulus != NULL)
  1988.         BSFree (pubkey->modulus);
  1989.     if (pubkey->exponent != NULL)
  1990.         BSFree (pubkey->exponent);
  1991.     MemFree(pubkey);
  1992.     return 0;
  1993. }
  1994.  
  1995.  
  1996. static int
  1997. readPubKey(NIPubKeyPtr pubkey)
  1998. {
  1999.     DataVal     value;
  2000.  
  2001.     if ((atp = AsnReadId(aip, amp, atp)) == NULL || atp != RSA_PUBKEY_bits)
  2002.         goto PubKeyFail;
  2003.     if (AsnReadVal(aip, atp, &value) < 0)
  2004.         goto PubKeyFail;
  2005.     pubkey->bits = (Int2) value.intvalue;
  2006.  
  2007.     /* modulus */
  2008.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2009.         goto PubKeyFail;
  2010.     if (AsnReadVal(aip, atp, &value) < 0)
  2011.         goto PubKeyFail;
  2012.     pubkey->modulus = (ByteStorePtr) value.ptrvalue;
  2013.  
  2014.     /* exponent */
  2015.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2016.         goto PubKeyFail;
  2017.     if (AsnReadVal(aip, atp, &value) < 0)
  2018.         goto PubKeyFail;
  2019.     pubkey->exponent = (ByteStorePtr) value.ptrvalue;
  2020.  
  2021.     /* end struct */
  2022.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2023.         goto PubKeyFail;
  2024.     if (AsnReadVal(aip, atp, &value) < 0)
  2025.         goto PubKeyFail;
  2026.     return 0;
  2027.  
  2028.   PubKeyFail:
  2029.     return -1;
  2030. }
  2031.  
  2032. static void
  2033. writePubKey(NIPubKeyPtr pubkey)
  2034. {
  2035.     DataVal     value;
  2036.  
  2037.     if (pubkey == NULL)
  2038.         return;
  2039.     value.intvalue = pubkey->bits;
  2040.     AsnWrite(aip, RSA_PUBKEY_bits, &value);
  2041.     value.ptrvalue = pubkey->modulus;
  2042.     AsnWrite(aip, RSA_PUBKEY_modulus, &value);
  2043.     value.ptrvalue = pubkey->exponent;
  2044.     AsnWrite(aip, RSA_PUBKEY_exponent, &value);
  2045. }
  2046.  
  2047. int
  2048. NI_ReadPubKey(AsnIoPtr extaip, AsnTypePtr extatp, NIPubKeyPtr pubkey)
  2049. {
  2050.     AsnIoPtr      savaip = aip;
  2051.     AsnTypePtr    savatp = atp;
  2052.     DataVal       value;
  2053.     int           retval = -1;
  2054.  
  2055.     if (! InitMsg())
  2056.         return 0;
  2057.     aip = extaip;
  2058.     atp = extatp;
  2059.     if ((atp = AsnReadId(aip, amp, atp)) == RSA_PUBKEY)
  2060.     {
  2061.         if (AsnReadVal(aip, atp, &value) >= 0)
  2062.         {
  2063.             retval = readPubKey(pubkey);
  2064.         }
  2065.    }
  2066.    aip = savaip;
  2067.    atp = savatp;
  2068.    return retval;
  2069. }
  2070.  
  2071. void
  2072. NI_WritePubKey(AsnIoPtr extaip, AsnTypePtr extatp, NIPubKeyPtr pubkey)
  2073. {
  2074.     AsnIoPtr savaip = aip;
  2075.     AsnTypePtr savatp = atp;
  2076.  
  2077.     if (! InitMsg())
  2078.         return;
  2079.     aip = extaip;
  2080.     atp = extatp;
  2081.     if (extatp != NULL)
  2082.         AsnStartStruct(extaip, extatp);
  2083.     writePubKey(pubkey);
  2084.     if (extatp != NULL)
  2085.         AsnEndStruct(extaip, extatp);
  2086.     aip = savaip;
  2087.     atp = savatp;
  2088. }
  2089.  
  2090.  
  2091.  
  2092. /************************************ DispInfo ********************************/
  2093.  
  2094. NIDispInfoPtr 
  2095. NI_MakeDispInfo(void)
  2096. {
  2097.     NIDispInfoPtr   dip;
  2098.     
  2099.     dip = (NIDispInfoPtr) MemNew(sizeof(NIDispInfo));
  2100.     dip->serialno = -1;
  2101.     dip->isalternatelist = FALSE;
  2102.     dip->numdispatchers = 0;
  2103.     dip->displist = NULL;
  2104.     dip->pubKey = NULL;
  2105.     return dip;
  2106. } /* NI_MakeDispInfo */
  2107.  
  2108.  
  2109. Int2 
  2110. NI_DestroyDispInfo(NIDispInfoPtr dip)
  2111. {
  2112.     Int2 num;
  2113.  
  2114.     if (dip == NULL)
  2115.         return 1;
  2116.     if (dip->displist != NULL)
  2117.     {
  2118.         for (num = 0; num < dip->numdispatchers; num++)
  2119.         {
  2120.             dip->displist[num] = (CharPtr) MemFree(dip->displist[num]);
  2121.         }
  2122.         MemFree(dip->displist);
  2123.     }
  2124.     if (dip->pubKey != NULL)
  2125.     {
  2126.         NI_DestroyPubKey(dip->pubKey);
  2127.     }
  2128.     MemFree(dip);
  2129.     return 0;
  2130. } /* NI_DestroyDispInfo */
  2131.  
  2132.  
  2133. static int 
  2134. readDispInfo(NIDispInfoPtr dip)
  2135. {
  2136.     DataVal     value;
  2137.     int         num;
  2138.  
  2139.     if ((atp = AsnReadId(aip, amp, atp)) == NULL || atp != DISPATCHER_INFO_serial_no)
  2140.         goto DispInfoFail;
  2141.     if (AsnReadVal(aip, atp, &value) < 0)
  2142.         goto DispInfoFail;
  2143.     dip->serialno = value.intvalue;
  2144.     
  2145.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* is altlist?*/
  2146.         goto DispInfoFail;
  2147.     if (atp == INFO_is_alternate_list) {
  2148.         if (AsnReadVal(aip, atp, &value) < 0)
  2149.             goto DispInfoFail;
  2150.         dip->isalternatelist = value.boolvalue;
  2151.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)           /* num disps ?*/
  2152.             goto DispInfoFail;
  2153.     }
  2154.     
  2155.     if (atp == DISPATCHER_INFO_num_dispatchers) {
  2156.         if (AsnReadVal(aip, atp, &value) < 0)
  2157.             goto DispInfoFail;
  2158.         dip->numdispatchers = (int) value.intvalue;
  2159.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)           /* disps ? */
  2160.             goto DispInfoFail;
  2161.     }
  2162.     if (atp == DISPATCHER_INFO_disp_list) {
  2163.         if (AsnReadVal(aip, atp, &value) < 0)
  2164.             goto DispInfoFail;
  2165.         dip->displist = (CharPtr PNTR) MemNew(sizeof(CharPtr) * dip->numdispatchers);
  2166.         atp = AsnReadId(aip, amp, atp);
  2167.         for (num = 0; num < dip->numdispatchers &&
  2168.              atp == DISPATCHER_INFO_disp_list_E; num++)
  2169.         {
  2170.             if (AsnReadVal(aip, atp, &value) <= 0)
  2171.                 goto DispInfoFail;
  2172.             dip->displist[num] = (CharPtr) value.ptrvalue;
  2173.             atp = AsnReadId(aip, amp, atp);
  2174.         }
  2175.         if (AsnReadVal(aip, atp, &value) <= 0)
  2176.             goto DispInfoFail;
  2177.         atp = AsnReadId(aip, amp, atp);
  2178.     }
  2179.     if (atp == DISPATCHER_INFO_pub_key) {
  2180.         if (AsnReadVal(aip, atp, &value) < 0)
  2181.             goto DispInfoFail;
  2182.         dip->pubKey = NI_MakePubKey();
  2183.         if (readPubKey(dip->pubKey) < 0)
  2184.             goto DispInfoFail;
  2185.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2186.             goto DispInfoFail;
  2187.     }
  2188.  
  2189.     if (AsnReadVal(aip, atp, &value) < 0)
  2190.         goto DispInfoFail;
  2191.     return 0;
  2192.  
  2193.   DispInfoFail:
  2194.     return -1;
  2195. } /* readDispInfo */
  2196.  
  2197.  
  2198. static void 
  2199. writeDispInfo(NIDispInfoPtr dip)
  2200. {
  2201.     DataVal     value;
  2202.     int         num;
  2203.     
  2204.     if (dip == NULL)
  2205.         return;
  2206.     value.intvalue = dip->serialno;
  2207.     AsnWrite(aip, DISPATCHER_INFO_serial_no, &value);
  2208.     value.boolvalue = dip->isalternatelist;
  2209.     AsnWrite(aip, INFO_is_alternate_list, &value);
  2210.     value.intvalue = dip->numdispatchers;
  2211.     AsnWrite(aip, DISPATCHER_INFO_num_dispatchers, &value);
  2212.     if (dip->displist != NULL) {
  2213.         AsnStartStruct (aip, DISPATCHER_INFO_disp_list);
  2214.         for (num = 0; num < dip->numdispatchers; num++) {
  2215.             value.ptrvalue = dip->displist[num];
  2216.             AsnWrite (aip, DISPATCHER_INFO_disp_list_E, &value);
  2217.         }
  2218.         AsnEndStruct (aip, DISPATCHER_INFO_disp_list);
  2219.     }
  2220.     if (dip->pubKey != NULL) {
  2221.         AsnStartStruct (aip, DISPATCHER_INFO_pub_key);
  2222.         writePubKey (dip->pubKey);
  2223.         AsnEndStruct (aip, DISPATCHER_INFO_pub_key);
  2224.     }
  2225. } /* writeDispInfo */
  2226.  
  2227. int 
  2228. NI_ReadDispInfo(AsnIoPtr extaip, AsnTypePtr extatp, NIDispInfoPtr dip)
  2229. {
  2230.     AsnIoPtr     savaip = aip;
  2231.     AsnTypePtr   savatp = atp;
  2232.     DataVal      value;
  2233.     int          retval = -1;
  2234.  
  2235.     if (! InitMsg())
  2236.         return 0;
  2237.     aip = extaip;
  2238.     atp = extatp;
  2239.     if ((atp = AsnReadId(aip, amp, atp)) == DISPATCHER_INFO)
  2240.     {
  2241.         if (AsnReadVal(aip, atp, &value) >= 0)
  2242.         {
  2243.             retval = readDispInfo(dip);
  2244.         }
  2245.     }
  2246.     aip = savaip;
  2247.     atp = savatp;
  2248.     return retval;
  2249. }
  2250.  
  2251. void
  2252. NI_WriteDispInfo(AsnIoPtr extaip, AsnTypePtr extatp, NIDispInfoPtr dip)
  2253. {
  2254.     AsnIoPtr savaip = aip;
  2255.     AsnTypePtr savatp = atp;
  2256.  
  2257.     if (! InitMsg())
  2258.         return;
  2259.     aip = extaip;
  2260.     atp = extatp;
  2261.     if (extatp != NULL)
  2262.         AsnStartStruct(extaip, extatp);
  2263.     writeDispInfo(dip);
  2264.     if (extatp != NULL)
  2265.         AsnEndStruct(extaip, extatp);
  2266.     aip = savaip;
  2267.     atp = savatp;
  2268. }
  2269.  
  2270.  
  2271. /************************************ TOOLSET *********************************/
  2272.  
  2273. NIToolsetPtr 
  2274. NI_MakeToolset(void)
  2275. {
  2276.     NIToolsetPtr        tsp;
  2277.     
  2278.     tsp = (NIToolsetPtr) MemNew(sizeof(NIToolset));
  2279.     tsp->host = NULL;
  2280.     tsp->motd = NULL;
  2281.     tsp->services = NULL;
  2282.     tsp->resources = NULL;
  2283.     tsp->regions = NULL;
  2284.     return tsp;
  2285. } /* NI_MakeToolset */
  2286.  
  2287.  
  2288. Int2 
  2289. NI_DestroyToolset(NIToolsetPtr tsp)
  2290. {
  2291.     NodePtr             np;
  2292.     
  2293.     if (tsp == NULL)
  2294.         return 1;
  2295.     if (tsp->host != NULL)
  2296.         MemFree(tsp->host);
  2297.     if (tsp->motd != NULL)
  2298.         MemFree(tsp->motd);
  2299.     
  2300.     if ((np = tsp->services) != NULL) {
  2301.         do {
  2302.             NI_DestroyService((NISvcPtr)np->elem);
  2303.             np = ListDelete(np);
  2304.         } while (np != NULL);
  2305.     }   
  2306.     
  2307.     if ((np = tsp->resources) != NULL) {
  2308.         do {
  2309.             NI_DestroyResource((NIResPtr)np->elem);
  2310.             np = ListDelete(np);
  2311.         } while (np != NULL);
  2312.     }   
  2313.     
  2314.     if ((np = tsp->regions) != NULL) {
  2315.         do {
  2316.             NI_DestroyRegion((NIRegionPtr)np->elem);
  2317.             np = ListDelete(np);
  2318.         } while (np != NULL);
  2319.     }   
  2320.     
  2321.     MemFree(tsp);
  2322.     return 0;
  2323. } /* NI_DestroyToolset */
  2324.  
  2325.  
  2326. NIToolsetPtr 
  2327. NI_GetCatToolset(NIToolsetPtr tsp)
  2328. {
  2329.     NIToolsetPtr        dtsp;
  2330.     NISvcPtr            svcp, tsvcp;
  2331.     NIResPtr            resp, tresp;
  2332.     NodePtr             np;
  2333.     
  2334.     dtsp = NI_MakeToolset();
  2335.     
  2336.     if (tsp->host != NULL)
  2337.         dtsp->host = StringSave(tsp->host);
  2338.     if (tsp->motd != NULL)
  2339.         dtsp->motd = StringSave(tsp->motd);
  2340.     
  2341.     if (tsp->services != NULL) {
  2342.         np = tsp->services->last;
  2343.         do {
  2344.             np = ListGetNext(np);
  2345.             svcp = (NISvcPtr) np->elem;
  2346.             /* note that services which are a "subset" of another listed */
  2347.             /* service are filtered-out here                             */
  2348.             if (svcp != NULL && svcp->subSetList == NULL) {
  2349.                 tsvcp = NI_MakeService();
  2350.                 if (svcp->name != NULL)
  2351.                     tsvcp->name = StringSave(svcp->name);
  2352.  
  2353.                 if (svcp->typeL != NULL)
  2354.                 { /* make a copy of the list */
  2355.                     tsvcp->typeL = ListStrCopy(svcp->typeL);
  2356.                 }
  2357.  
  2358.                 tsvcp->minVersion = svcp->minVersion;
  2359.                 tsvcp->maxVersion = svcp->maxVersion;
  2360.                 tsvcp->priority = svcp->priority;
  2361.                 tsvcp->id = 0;          /* these two not sent in catalog */
  2362.                 tsvcp->group = NULL;
  2363.                 if (svcp->descrip != NULL)
  2364.                     tsvcp->descrip = StringSave(svcp->descrip);
  2365.                 dtsp->services = ListInsert((VoidPtr) tsvcp, dtsp->services);
  2366.             }
  2367.         } while (np != tsp->services->last);
  2368.         if (dtsp->services != NULL)
  2369.         {
  2370.             dtsp->services = dtsp->services->next;  /* point to first */
  2371.         }
  2372.     }
  2373.     
  2374.     if (tsp->resources != NULL) {
  2375.         np = tsp->resources->last;
  2376.         do {
  2377.             np = ListGetNext(np);
  2378.             resp = (NIResPtr) np->elem;
  2379.             if (resp != NULL) {
  2380.                 tresp = NI_MakeResource();
  2381.                 if (resp->name != NULL)
  2382.                     tresp->name = StringSave(resp->name);
  2383.                 if (resp->type != NULL)
  2384.                     tresp->type = StringSave(resp->type);
  2385.                 tresp->minVersion = resp->minVersion;
  2386.                 tresp->maxVersion = resp->maxVersion;
  2387.                 tresp->id = 0;          /* these two not sent in catalog */
  2388.                 tresp->group = NULL;
  2389.                 if (resp->descrip != NULL)
  2390.                     tresp->descrip = StringSave(resp->descrip);
  2391.                 dtsp->resources = ListInsert((VoidPtr) tresp, dtsp->resources);
  2392.             }
  2393.         } while (np != tsp->resources->last);
  2394.         if (dtsp->resources != NULL)
  2395.         {
  2396.             dtsp->resources = dtsp->resources->next;        /* point to first */
  2397.         }
  2398.     }
  2399.     
  2400.     return dtsp;
  2401. } /* NI_GetCatToolset */
  2402.  
  2403.  
  2404. static int
  2405. readToolset(NIToolsetPtr tsp)
  2406. {
  2407.     DataVal     value;
  2408.     NISvcPtr    svcp;
  2409.     NIResPtr    resp;
  2410.     NIRegionPtr reg;
  2411.     
  2412.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)       /* TOOLSET_host */
  2413.         goto ToolsetFail;
  2414.     if (AsnReadVal(aip, atp, &value) < 0)
  2415.         goto ToolsetFail;
  2416.     tsp->host = (CharPtr) value.ptrvalue;
  2417.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2418.         goto ToolsetFail;
  2419.     
  2420.     if (atp == TOOLSET_motd) {                  /* TOOLSET_motd ? */
  2421.         if (AsnReadVal(aip, atp, &value) < 0)
  2422.             goto ToolsetFail;
  2423.         tsp->motd = (CharPtr) value.ptrvalue;
  2424.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2425.             goto ToolsetFail;
  2426.     }
  2427.     if (atp == TOOLSET_services) {
  2428.         if (AsnReadVal(aip, atp, &value) < 0)
  2429.             goto ToolsetFail;
  2430.         while ((atp = AsnReadId(aip, amp, atp)) == TOOLSET_services_E) {
  2431.             if (AsnReadVal(aip, atp, &value) < 0)
  2432.                 goto ToolsetFail;
  2433.             svcp = NI_MakeService();
  2434.             readService(svcp);
  2435.             tsp->services = ListInsert((VoidPtr) svcp, tsp->services);
  2436.         }
  2437.         if (atp == NULL)
  2438.             goto ToolsetFail;
  2439.         tsp->services = tsp->services->next;    /* point to first */
  2440.         if (AsnReadVal(aip, atp, &value) < 0)
  2441.             goto ToolsetFail;
  2442.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2443.             goto ToolsetFail;
  2444.     }
  2445.     if (atp == TOOLSET_resources) {
  2446.         if (AsnReadVal(aip, atp, &value) < 0)
  2447.             goto ToolsetFail;
  2448.         while ((atp = AsnReadId(aip, amp, atp)) == TOOLSET_resources_E) {
  2449.             if (AsnReadVal(aip, atp, &value) < 0)
  2450.                 goto ToolsetFail;
  2451.             resp = NI_MakeResource();
  2452.             readResource(resp);
  2453.             tsp->resources = ListInsert((VoidPtr) resp, tsp->resources);
  2454.         }
  2455.         if (atp == NULL)
  2456.             goto ToolsetFail;
  2457.         tsp->resources = tsp->resources->next;  /* point to first */
  2458.         if (AsnReadVal(aip, atp, &value) < 0)
  2459.             goto ToolsetFail;
  2460.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2461.             goto ToolsetFail;
  2462.     }
  2463.     if (atp == TOOLSET_regions) {
  2464.         if (AsnReadVal(aip, atp, &value) < 0)
  2465.             goto ToolsetFail;
  2466.         while ((atp = AsnReadId(aip, amp, atp)) == TOOLSET_regions_E) {
  2467.             if (AsnReadVal(aip, atp, &value) < 0)
  2468.                 goto ToolsetFail;
  2469.             reg = NI_MakeRegion();
  2470.             readRegion(reg);
  2471.             tsp->regions = ListInsert((VoidPtr) reg, tsp->regions);
  2472.         }
  2473.         if (atp == NULL)
  2474.             goto ToolsetFail;
  2475.         tsp->regions = tsp->regions->next;  /* point to first */
  2476.         if (AsnReadVal(aip, atp, &value) < 0)
  2477.             goto ToolsetFail;
  2478.         if ((atp = AsnReadId(aip, amp, atp)) == NULL)
  2479.             goto ToolsetFail;
  2480.     }
  2481.  
  2482.     if (AsnReadVal(aip, atp, &value) < 0)
  2483.         goto ToolsetFail;
  2484.     return 0;
  2485.  
  2486.   ToolsetFail:
  2487.     return -1;
  2488. } /* readToolset */
  2489.  
  2490. static void 
  2491. writeToolset(NIToolsetPtr tsp)
  2492. {
  2493.     DataVal     value;
  2494.     NodePtr     np, lastnode;
  2495.     
  2496.     if (tsp->host != NULL)
  2497.         value.ptrvalue = (Pointer) tsp->host;
  2498.     else
  2499.         value.ptrvalue = (Pointer) StringSave("N/A");
  2500.     AsnWrite(aip, TOOLSET_host, &value);
  2501.     
  2502.     if (tsp->motd != NULL) {
  2503.         value.ptrvalue = (Pointer) tsp->motd;
  2504.         AsnWrite(aip, TOOLSET_motd, &value);
  2505.     }
  2506.     np = tsp->services;
  2507.     if (np != NULL) {
  2508.         AsnStartStruct(aip, TOOLSET_services);
  2509.         lastnode = np->last;
  2510.         while (np != NULL) {
  2511.             AsnStartStruct(aip, TOOLSET_services_E);
  2512.             writeService((NISvcPtr) np->elem);
  2513.             AsnEndStruct(aip, TOOLSET_services_E);
  2514.             if (np == lastnode)
  2515.                 break;
  2516.             np = np->next;
  2517.         }
  2518.         AsnEndStruct(aip, TOOLSET_services);
  2519.     }
  2520.     np = tsp->resources;
  2521.     if (np != NULL) {
  2522.         AsnStartStruct(aip, TOOLSET_resources);
  2523.         lastnode = np->last;
  2524.         while (np != NULL) {
  2525.             AsnStartStruct(aip, TOOLSET_resources_E);
  2526.             writeResource((NIResPtr) np->elem);
  2527.             AsnEndStruct(aip, TOOLSET_resources_E);
  2528.             if (np == lastnode)
  2529.                 break;
  2530.             np = np->next;
  2531.         }
  2532.         AsnEndStruct(aip, TOOLSET_resources);
  2533.     }
  2534.     np = tsp->regions;
  2535.     if (np != NULL) {
  2536.         AsnStartStruct(aip, TOOLSET_regions);
  2537.         lastnode = np->last;
  2538.         while (np != NULL) {
  2539.             AsnStartStruct(aip, TOOLSET_regions_E);
  2540.             writeRegion((NIRegionPtr) np->elem);
  2541.             AsnEndStruct(aip, TOOLSET_regions_E);
  2542.             if (np == lastnode)
  2543.                 break;
  2544.             np = np->next;
  2545.         }
  2546.         AsnEndStruct(aip, TOOLSET_regions);
  2547.     }
  2548. } /* writeToolset */
  2549.  
  2550.  
  2551. /******************************************************************************/
  2552. /*                                                                            */
  2553. /*      Message and Handle Functions                                          */
  2554. /*                                                                            */
  2555. /******************************************************************************/
  2556.  
  2557. /*
  2558.  * Purpose:     "High level" message read for ASN.1 messages
  2559.  *
  2560.  * Parameters:
  2561.  *   hp           "Message handle", describing parameters of input environment
  2562.  *   unblocked    Flag indicating whether input should "block" if unable
  2563.  *                to read a complete message
  2564.  *
  2565.  * Returns:
  2566.  *                NULL, if unable to read a message ... if hp->have_blocked is
  2567.  *                  set, then this reflects an inability to read a complete
  2568.  *                  message at this time
  2569.  *                a pointer to the message which was just read, otherwise
  2570.  *
  2571.  *
  2572.  * Description:
  2573.  *              Try to read a message from the socket specified by the hp
  2574.  *              data structure. A message must begin with the "MESSAGE" 
  2575.  *              identifier, followed by the type of the message. Once the
  2576.  *              type of the message has been determined, the remainder of
  2577.  *              the message is read using the corresponding readXXX()
  2578.  *              function.
  2579.  *
  2580.  *              Matters are more complex when the "unblocked" parameter
  2581.  *              is TRUE. In this case, if a failure occurs on a message read,
  2582.  *              an attempt is made to see whether any bytes of data were
  2583.  *              read from the socket upon this invocation. If so, the
  2584.  *              have_blocked flag is set for the caller, and AsnIoReset() is
  2585.  *              called to deal with a future attempt to read from this socket
  2586.  *              when more data becomes available.
  2587.  *
  2588.  * Note:
  2589.  *              This is the highest level read function which should be
  2590.  *              called by an application program. All the other "static"
  2591.  *              functions called here should not be called directly by an
  2592.  *              application program.
  2593.  *
  2594.  *              The ASN.1 error handling is performing using the setjmp()/
  2595.  *              longjmp() paradigm, where a function can return to an earlier
  2596.  *              context if an error occurs.
  2597.  *
  2598.  *              Currently, it is not possible to distinguish
  2599.  *              between an ASN.1 format error, and an ASN failure due to
  2600.  *              inability to read the requested quantity of data. For this
  2601.  *              reason, if the "unblocked" option is selected, it will take
  2602.  *              hp->r_timeout seconds to detect either of these
  2603.  *              conditions. In the best of all possible worlds, it would
  2604.  *              be possible to distinguish between "data not YET available"
  2605.  *              and "invalid data" conditions.
  2606.  */
  2607.  
  2608. NIMsgPtr 
  2609. MsgRead(MHandPtr hp, Boolean unblocked)
  2610. {
  2611.     DataVal     value;
  2612.     NIMsgPtr    mp = NULL;
  2613.     int         start_byte_count = hp->num_queued_bytes;
  2614.     NodePtr     timer = NULL;
  2615.  
  2616.     ni_errno = NIE_MSGREAD;
  2617.  
  2618.     hp->unblocked_mode = unblocked;
  2619.     hp->have_blocked = FALSE;
  2620.  
  2621.     /* for unblocked I/O, set a "hangup" timeout which can be detected at    */
  2622.     /* at later time, if we are unable to read a complete or valid message   */
  2623.     if (unblocked && hp->readTimeoutHook != NULL)
  2624.         timer = NI_SetTimer(time(NULL) + hp->r_timeout, hp->readTimeoutHook,
  2625.                             (VoidPtr) hp);
  2626.     hp->readTimer = timer;
  2627.         
  2628.     if (hp->longjump == TRUE) {
  2629.         if (SetJump(ni_env)) {
  2630.             /* return from LongJump (error handler) */
  2631.             goto MsgReadFail;
  2632.         }
  2633.     }
  2634.  
  2635.     StringCpy(ni_errtext, "AsnReadId or AsnReadVal returned bad value");
  2636.     aip = hp->raip;
  2637.     atp = MESSAGE;
  2638.     if ((atp = AsnReadId(aip, amp, atp)) != MESSAGE)    /* Must read a MESSAGE */
  2639.         goto MsgReadFail;       /* don't have to read val as Null return is always fatal to channel */
  2640.     if (AsnReadVal(aip, atp, &value) < 0)
  2641.         goto MsgReadFail;
  2642.     
  2643.     if ((atp = AsnReadId(aip, amp, atp)) == NULL)               /* type of message */
  2644.         goto MsgReadFail;
  2645.     if (AsnReadVal(aip, atp, &value) < 0)
  2646.         goto MsgReadFail;
  2647.     
  2648.     mp = (NIMsgPtr) MemNew(sizeof(NIMessage));
  2649.     mp->conid = hp->conid;
  2650.     mp->type = NI_UNKNOWN;
  2651.     
  2652.     if (atp == MESSAGE_ack) {
  2653.         if ((mp->msun.ack = readACK()) != NULL)
  2654.             mp->type = NI_ACK;
  2655.         goto gotmessage;
  2656.     }
  2657.     
  2658.     if (atp == MESSAGE_nack) {
  2659.         if ((mp->msun.nack = readNACK()) != NULL)
  2660.             mp->type = NI_NACK;
  2661.         goto gotmessage;
  2662.     }
  2663.     
  2664.     if (atp == MESSAGE_login) {
  2665.         if ((mp->msun.login = readLOGIN()) != NULL)
  2666.             mp->type = NI_LOGIN;
  2667.         goto gotmessage;
  2668.     }
  2669.     
  2670.     if (atp == MESSAGE_svc_list) {
  2671.         if ((mp->msun.svclist = readSVC_LIST()) != NULL)
  2672.             mp->type = NI_SVC_LIST;
  2673.         goto gotmessage;
  2674.     }
  2675.     
  2676.     if (atp == MESSAGE_svc_request) {
  2677.         if ((mp->msun.svcreq = readSVC_REQUEST()) != NULL)
  2678.             mp->type = NI_SVC_REQUEST;
  2679.         goto gotmessage;
  2680.     }
  2681.     
  2682.     if (atp == MESSAGE_svc_response) {
  2683.         if ((mp->msun.svcresp = readSVC_RESPONSE()) != NULL)
  2684.             mp->type = NI_SVC_RESPONSE;
  2685.         goto gotmessage;
  2686.     }
  2687.     
  2688.     if (atp == MESSAGE_command) {
  2689.         if ((mp->msun.command = readCOMMAND()) != NULL)
  2690.             mp->type = NI_COMMAND;
  2691.         goto gotmessage;
  2692.     }
  2693.     
  2694.     if (atp == MESSAGE_svc_pre_response) {
  2695.         if ((mp->msun.preresp = readPRE_RESPONSE()) != NULL)
  2696.             mp->type = NI_SVC_PRE_RESPONSE;
  2697.         goto gotmessage;
  2698.     }
  2699.     
  2700.     if (atp == MESSAGE_acct) {
  2701.         if ((mp->msun.acct = readACCT()) != NULL)
  2702.             mp->type = NI_ACCT;
  2703.         goto gotmessage;
  2704.     }
  2705.     
  2706.     if (atp == MESSAGE_catalog) {
  2707.         if ((mp->msun.catalog = readCATALOG()) != NULL)
  2708.             mp->type = NI_CATALOG;
  2709.         goto gotmessage;
  2710.     }
  2711.     
  2712.   gotmessage:
  2713.     if (mp->type == NI_UNKNOWN) {
  2714.         StringCpy(ni_errtext, "unknown msg type");
  2715.         goto MsgReadFail;
  2716.     }
  2717.     else { /* got good stuff */
  2718.         MsgFreeSavedData(hp); /* free associated data */
  2719.         hp->unblocked_mode = FALSE;
  2720.         hp->have_blocked = FALSE;
  2721.         NI_CancelTimer (hp->readTimer);
  2722.         hp->readTimer = NULL;
  2723.         return mp;
  2724.     }
  2725.     
  2726.   MsgReadFail:
  2727.     if (mp != NULL)
  2728.         MsgDestroy(mp);
  2729.  
  2730.     /* if ( things didn't go well, but there was more data read from the     */
  2731.     /*      socket ) then                                                    */
  2732.     if (start_byte_count < hp->num_queued_bytes)
  2733.         hp->have_blocked = TRUE; /* set things up to try again */
  2734.  
  2735.     if (hp->have_blocked)
  2736.     { /* failed due to data unavailability */
  2737.         hp->cur_index = 0; /* reset queued read pointer */
  2738.         AsnIoReset (aip);  /* reset ASN input stream */
  2739.         /* caller should try again later, based upon detecting hp->have_blocked */
  2740.     }
  2741.     hp->unblocked_mode = FALSE;
  2742.     return NULL;
  2743. } /* MsgRead */
  2744.  
  2745.  
  2746.  
  2747. /*
  2748.  * Purpose:     "High level" message write for ASN.1 messages
  2749.  *
  2750.  * Parameters:
  2751.  *   hp           "Message handle", describing parameters of I/O environment
  2752.  *   mp           Message to be written
  2753.  *   noDestroy    If set, refrain from destroying the message
  2754.  *
  2755.  * Returns:
  2756.  *                -1, if unable to write the message
  2757.  *                0, otherwise
  2758.  *
  2759.  *
  2760.  * Description:
  2761.  *              Try to write a message from the socket specified by the hp
  2762.  *              data structure. The writing of the message is performed
  2763.  *              using the writeXXX() function which corresponds to the type
  2764.  *              of the message to be written.
  2765.  */
  2766.  
  2767. Int2 
  2768. MsgWrite(MHandPtr hp, NIMsgPtr mp, Boolean noDestroy)
  2769. {
  2770.     DataVal     value;
  2771.  
  2772.     ni_errno = NIE_MSGWRITE;
  2773.  
  2774.     if (hp->longjump == TRUE) {
  2775.         if (SetJump(ni_env)) {
  2776.             /* return from LongJump (error handler) */
  2777.             if (! noDestroy)
  2778.                 MsgDestroy(mp);             /* failing, so destroy it */    
  2779.             return -1;
  2780.         }
  2781.     }
  2782.     
  2783.     aip = hp->waip;
  2784.     AsnWrite(aip, MESSAGE, &value);
  2785.     
  2786.     switch (mp->type) {
  2787.       case NI_ACK:
  2788.         writeACK(mp->msun.ack);
  2789.         break;
  2790.         
  2791.       case NI_NACK:
  2792.         writeNACK(mp->msun.nack);
  2793.         break;
  2794.         
  2795.       case NI_LOGIN:
  2796.         writeLOGIN(mp->msun.login);
  2797.         break;
  2798.         
  2799.       case NI_SVC_LIST:
  2800.         writeSVC_LIST(mp->msun.svclist);
  2801.         break;
  2802.         
  2803.       case NI_SVC_REQUEST:
  2804.         writeSVC_REQUEST(mp->msun.svcreq);
  2805.         break;
  2806.         
  2807.       case NI_SVC_RESPONSE:
  2808.         writeSVC_RESPONSE(mp->msun.svcresp);
  2809.         break;
  2810.         
  2811.       case NI_COMMAND:
  2812.         writeCOMMAND(mp->msun.command);
  2813.         break;
  2814.         
  2815.       case NI_SVC_PRE_RESPONSE:
  2816.         writePRE_RESPONSE(mp->msun.preresp);
  2817.         break;
  2818.         
  2819.       case NI_ACCT:
  2820.         writeACCT(mp->msun.acct);
  2821.         break;
  2822.         
  2823.       case NI_CATALOG:
  2824.         writeCATALOG(mp->msun.catalog);
  2825.         break;
  2826.         
  2827.       default:
  2828.         ni_errno = NIE_MSGUNK;
  2829.         StringCpy(ni_errtext, "unable to write msg");
  2830.         if (! noDestroy)
  2831.             MsgDestroy(mp);
  2832.         return -1;
  2833.     }
  2834.     
  2835.     AsnIoFlush(aip);
  2836.     if (! noDestroy)
  2837.         MsgDestroy(mp);
  2838.     return 0;
  2839. } /* MsgWrite */
  2840.  
  2841.  
  2842.  
  2843. /*
  2844.  * Purpose:     Build a message of the specified type, populating it with
  2845.  *              a pointer to the actual message data, and the connection ID.
  2846.  *
  2847.  * Parameters:
  2848.  *   type         The type of message to be built
  2849.  *   conn         Connection ID associated with this session
  2850.  *   stp          Pointer to the actual message data
  2851.  *
  2852.  * Returns:
  2853.  *                NULL, if unable to allocate memory for the message, or if
  2854.  *                      the specified message type is invalid
  2855.  *                a pointer to the newly-build message, otherwise
  2856.  *
  2857.  *
  2858.  * Description:
  2859.  *              Create a message data structure, and populate it as indicated.
  2860.  */
  2861.  
  2862. NIMsgPtr
  2863. MsgBuild(MsgType type, Uint4 conn, VoidPtr stp)
  2864. {
  2865.     NIMsgPtr            mp;
  2866.     
  2867.     if (! InitMsg())
  2868.         return NULL;
  2869.     mp = (NIMsgPtr) MemNew(sizeof(NIMessage));
  2870.     if (mp == NULL)
  2871.         return NULL;
  2872.     mp->type = type;
  2873.     mp->conid = conn;
  2874.     
  2875.     switch (mp->type) {
  2876.       case NI_ACK:
  2877.         mp->msun.ack = (NIAckPtr) stp;
  2878.         break;
  2879.         
  2880.       case NI_NACK:
  2881.         mp->msun.nack = (NINackPtr) stp;
  2882.         break;
  2883.         
  2884.       case NI_LOGIN:
  2885.         mp->msun.login = (NILoginPtr) stp;
  2886.         break;
  2887.         
  2888.       case NI_SVC_LIST:
  2889.         mp->msun.svclist = (NISvcListPtr) stp;
  2890.         break;
  2891.         
  2892.       case NI_SVC_REQUEST:
  2893.         mp->msun.svcreq = (NISvcReqPtr) stp;
  2894.         break;
  2895.         
  2896.       case NI_SVC_RESPONSE:
  2897.         mp->msun.svcresp = (NISvcRespPtr) stp;
  2898.         break;
  2899.         
  2900.       case NI_COMMAND:
  2901.         mp->msun.command = (NICmdPtr) stp;
  2902.         break;
  2903.         
  2904.       case NI_SVC_PRE_RESPONSE:
  2905.         mp->msun.preresp = (NIPreRespPtr) stp;
  2906.         break;
  2907.         
  2908.       case NI_ACCT:
  2909.         mp->msun.acct = (NIAcctPtr) stp;
  2910.         break;
  2911.         
  2912.       case NI_CATALOG:
  2913.         mp->msun.catalog = (NICatalogPtr) stp;
  2914.         break;
  2915.         
  2916.       default:
  2917.         ni_errno = NIE_MSGUNK;
  2918.         StringCpy(ni_errtext, "unable to build");
  2919.         MemFree (mp);
  2920.         return NULL;
  2921.     }
  2922.     return mp;
  2923. } /* MsgBuild */
  2924.  
  2925.  
  2926.  
  2927. /*
  2928.  * Purpose:     Destroy the specified message
  2929.  *
  2930.  * Parameters:
  2931.  *   mp           A pointer to the message structure to be destroyed
  2932.  *
  2933.  * Returns:
  2934.  *                -1, if the specified pointer is NULL, or if the message
  2935.  *                    is of an unknown type
  2936.  *                0, otherwise
  2937.  *
  2938.  *
  2939.  * Description:
  2940.  *              Destroy the specified message, using the appropriate message
  2941.  *              destructor function.
  2942.  */
  2943.  
  2944. Int2 
  2945. MsgDestroy(NIMsgPtr mp)
  2946. {
  2947.     if (mp == NULL)
  2948.         return -1;
  2949.     
  2950.     switch (mp->type) {
  2951.       case NI_ACK:
  2952.         NI_DestroyMsgAck(mp->msun.ack);
  2953.         break;
  2954.         
  2955.       case NI_NACK:
  2956.         NI_DestroyMsgNack(mp->msun.nack);
  2957.         break;
  2958.         
  2959.       case NI_LOGIN:
  2960.         NI_DestroyMsgLogin(mp->msun.login);
  2961.         break;
  2962.         
  2963.       case NI_SVC_LIST:
  2964.         NI_DestroyMsgSvclist(mp->msun.svclist);
  2965.         break;
  2966.         
  2967.       case NI_SVC_REQUEST:
  2968.         NI_DestroyMsgSvcreq(mp->msun.svcreq);
  2969.         break;
  2970.         
  2971.       case NI_SVC_RESPONSE:
  2972.         NI_DestroyMsgSvcresp(mp->msun.svcresp);
  2973.         break;
  2974.         
  2975.       case NI_COMMAND:
  2976.         NI_DestroyMsgCmd(mp->msun.command);
  2977.         break;
  2978.         
  2979.       case NI_SVC_PRE_RESPONSE:
  2980.         NI_DestroyMsgPreResp(mp->msun.preresp);
  2981.         break;
  2982.         
  2983.       case NI_ACCT:
  2984.         NI_DestroyMsgAcct(mp->msun.acct);
  2985.         break;
  2986.         
  2987.       case NI_CATALOG:
  2988.         NI_DestroyMsgCatalog(mp->msun.catalog);
  2989.         break;
  2990.         
  2991.       default:
  2992.         ni_errno = NIE_MSGUNK;
  2993.         StringCpy(ni_errtext, "unable to destroy msg");
  2994.         MemFree(mp);
  2995.         return -1;
  2996.     }
  2997.  
  2998.     MemFree(mp);
  2999.     return 0;
  3000. } /* MsgDestroy */
  3001.  
  3002.  
  3003.  
  3004. /*
  3005.  * Purpose:     Create a message handle
  3006.  *
  3007.  * Returns:
  3008.  *                NULL, if unable to allocate the required memory, open
  3009.  *                    a socket, set the socket to non-blocking mode, or
  3010.  *                    initialize the ASN.1 I/O streams successfully
  3011.  *                a pointer to the new message handle, otherwise
  3012.  *
  3013.  *
  3014.  * Description:
  3015.  *              Create a "message" handle, which is the basic unit of message
  3016.  *              I/O. A message handle includes, among other things, a logical
  3017.  *              connection ID, a socket used for both input and output, ASN.1
  3018.  *              I/O stream pointers, and a queue of input data which has
  3019.  *              already been read from the socket, but has not yet been
  3020.  *              processed successfully using ASN.1.
  3021.  *
  3022.  * Note:
  3023.  *              This is currently the only place where conid is incremented,
  3024.  *              and therefore, the only place where conid is written to the
  3025.  *              Conid file.
  3026.  */
  3027.  
  3028. MHandPtr 
  3029. MsgMakeHandle(Boolean createSocket)
  3030. {
  3031.     MHandPtr    mh;
  3032.     
  3033.     if (! InitMsg()) {
  3034.         StringCpy(ni_errtext, "Network services ASN.1 initialization failed");
  3035.         ni_errno = NIE_ASN1SPECFAIL;
  3036.         return NULL;
  3037.     }
  3038.     if ((mh = (MHandPtr) MemNew(sizeof(MHandle))) == NULL) {
  3039.         StringCpy(ni_errtext, "unable to allocate new memory");
  3040.         return NULL;
  3041.     }
  3042.     mh->hostname = NULL;
  3043.     mh->conid = conid++;
  3044.     WriteConFile(conid);
  3045.     mh->seqno = 1;
  3046.     mh->sok = -1;
  3047.  
  3048.     if (createSocket) {
  3049.         if ((mh->sok = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) ==
  3050.             INVALID_SOCKET) {
  3051. #ifdef NETP_INET_NEWT
  3052.             SOCK_ERRNO = ABS(mh->sok);
  3053. #endif
  3054.             StringCpy(ni_errtext, sys_errlist[SOCK_INDEX_ERRNO]);
  3055.             MemFree(mh);
  3056.             return NULL;
  3057.         }
  3058.         LOG_SOCKET(mh->sok, TRUE);
  3059.         if (NI_SETNONBLOCKING(mh->sok) == -1) {
  3060.             StringCpy(ni_errtext, sys_errlist[SOCK_INDEX_ERRNO]);
  3061.             MemFree(mh);
  3062.             return NULL;
  3063.         }
  3064.     }
  3065.     mh->r_timeout = NI_READ_TIMEOUT;
  3066.     mh->w_timeout = NI_WRITE_TIMEOUT;
  3067.     mh->state = NI_CREATED;
  3068.     mh->extra_proc_info = NULL;
  3069.     mh->read_filter = NULL;
  3070.     mh->write_filter = NULL;
  3071.     mh->write_filt_pass_thru = TRUE;
  3072.     mh->read_filt_pass_thru = TRUE;
  3073.     mh->readTimeoutHook = NULL;
  3074.     mh->writeTimeoutHook = NULL;
  3075.     mh->readTimer = NULL;
  3076.     mh->writeTimer = NULL;
  3077.     mh->encryption = NULL;
  3078.     mh->isBrokered = FALSE;
  3079.     mh->brokeredPort = 0;
  3080.     mh->peer = 0;
  3081.     if ((mh->raip = AsnIoNew((ASNIO_BIN | ASNIO_IN), (FILE *) NULL, (Pointer) mh, NI_AsnRead, NI_AsnWrite)) == NULL) {
  3082.         LOG_SOCKET(mh->sok, FALSE);
  3083.         NI_CLOSESOCKET(mh->sok);
  3084.         StringCpy(ni_errtext, "unable to allocate new AsnIoPtr (raip)");
  3085.         MemFree(mh);
  3086.         return NULL;
  3087.     }
  3088.     if ((mh->waip = AsnIoNew((ASNIO_BIN | ASNIO_OUT), (FILE *) NULL, (Pointer) mh, NI_AsnRead, NI_AsnWrite)) == NULL) {
  3089.         AsnIoClose(mh->raip);
  3090.         LOG_SOCKET(mh->sok, FALSE);
  3091.         NI_CLOSESOCKET(mh->sok);
  3092.         StringCpy(ni_errtext, "unable to allocate new AsnIoPtr (waip)");
  3093.         MemFree(mh);
  3094.         return NULL;
  3095.     }
  3096.     AsnIoSetBufsize(mh->waip, NI_BLOCKSIZE);
  3097.     mh->longjump = FALSE;
  3098.     mh->access_time = time(NULL);
  3099.     mh->have_blocked = FALSE;
  3100.     mh->num_queued_bytes = 0;
  3101.     mh->cur_index = 0;
  3102.     mh->queued_data_list = NULL;
  3103.     mh->unblocked_mode = FALSE;
  3104.     return mh; 
  3105. } /* MsgMakeHandle */
  3106.  
  3107.  
  3108.  
  3109. /*
  3110.  * Purpose:     Destroy the specified message handle
  3111.  *
  3112.  * Parameters:
  3113.  *   hp           A pointer to the message handle to be destroyed
  3114.  *
  3115.  * Returns:
  3116.  *                -1, if the specified pointer is NULL
  3117.  *                0, otherwise
  3118.  *
  3119.  *
  3120.  * Description:
  3121.  *              Destroy the specified message handle, close its socket,
  3122.  *              close the ASN streams, and free any associated queued data.
  3123.  */
  3124.  
  3125. Int2 
  3126. MsgDestroyHandle(MHandPtr hp)
  3127. {
  3128.     if (hp == NULL)
  3129.         return -1;
  3130.     if (hp->sok != INVALID_SOCKET)
  3131.     {
  3132.         LOG_SOCKET(hp->sok, FALSE);
  3133.         NI_CLOSESOCKET(hp->sok);
  3134.     }
  3135.     if (hp->hostname != NULL)
  3136.         MemFree(hp->hostname);
  3137.     NI_CancelTimer(hp->readTimer);
  3138.     NI_CancelTimer(hp->writeTimer);
  3139.     AsnIoClose(hp->raip);
  3140.     AsnIoClose(hp->waip);
  3141.     if (hp->encryption != NULL)
  3142.     {
  3143.         NI_DestroyEncrStruct(hp->encryption);
  3144.     }
  3145.     MsgFreeSavedData(hp);
  3146.     MemFree(hp);
  3147.     return 0;
  3148. } /* MsgDestroyHandle */
  3149.  
  3150.  
  3151.  
  3152. /*
  3153.  * Purpose:     Set "longjump" error mechanism
  3154.  *
  3155.  * Parameters:
  3156.  *   mh           A pointer to the message handle for which the "longjump"
  3157.  *                error is to be set.
  3158.  *
  3159.  *
  3160.  * Description:
  3161.  *              Set the ASN I/O error handler to be a function which will
  3162.  *              simply "longjump", and hence return control to the place at
  3163.  *              which setjmp() was last called. The "longjump" flag should
  3164.  *              be check by a setjmp() caller, prior to calling setjmp(), to
  3165.  *              assure that the error handling mechanism is in place.
  3166.  */
  3167.  
  3168. void 
  3169. MsgSetLJError(MHandPtr mh)
  3170. {
  3171.     AsnIoSetErrorMsg(mh->raip, NI_ASNIOError);
  3172.     AsnIoSetErrorMsg(mh->waip, NI_ASNIOError);
  3173.     mh->longjump = TRUE;
  3174. } /* MsgSetLJError */
  3175.  
  3176.  
  3177.  
  3178. /*
  3179.  * Purpose:     Set the "read" timeout for this message handle
  3180.  *
  3181.  * Parameters:
  3182.  *   mh           A pointer to the message handle for which the read timeout
  3183.  *                is to be set.
  3184.  *
  3185.  *
  3186.  * Description:
  3187.  *              Set the "read" timeout for this message handle. A default
  3188.  *              value is set-up at the time when the message handle is created.
  3189.  *
  3190.  * Note:
  3191.  *              This timeout is also used for the "hung" timeout.
  3192.  */
  3193.  
  3194. void 
  3195. MsgSetReadTimeout(MHandPtr mh, int t)
  3196. {
  3197.     mh->r_timeout = t;
  3198. } /* MsgSetReadTimeout */
  3199.  
  3200.  
  3201. /*
  3202.  * Purpose:     Set the "write" timeout for this message handle
  3203.  *
  3204.  * Parameters:
  3205.  *   mh           A pointer to the message handle for which the write timeout
  3206.  *                is to be set.
  3207.  *
  3208.  *
  3209.  * Description:
  3210.  *              Set the "write" timeout for this message handle. A default
  3211.  *              value is set-up at the time when the message handle is created.
  3212.  */
  3213.  
  3214. void 
  3215. MsgSetWriteTimeout(MHandPtr mh, int t)
  3216. {
  3217.     mh->w_timeout = t;
  3218. } /* MsgSetWriteTimeout */
  3219.  
  3220.  
  3221. /*
  3222.  * Purpose:     Set the filter parameters for this message handle
  3223.  *
  3224.  * Parameters:
  3225.  *   mh           A pointer to the message handle for which the parameters
  3226.  *                are to be set.
  3227.  *
  3228.  *   ex_proc      A pointer to an optional user-defined data structure to be
  3229.  *                used by the read and write filters.
  3230.  *
  3231.  *   wfilt        A write filter function, which may be used, e.g., to collect
  3232.  *                statistics, or to compress the data to be written.
  3233.  *
  3234.  *   rfilt        A read filter function, which may be used, e.g., to collect
  3235.  *                statistics, or to decompress the data which was read.
  3236.  *
  3237.  *   wfilt_pass   Indicates whether wfilt needs to modify the data buffer (e.g.,
  3238.  *                this will be FALSE if doing statistics only, but TRUE if
  3239.  *                doing data compression).
  3240.  *
  3241.  *   rfilt_pass   Indicates whether rfilt needs to return a modified data
  3242.  *                buffer (e.g., this will be FALSE if doing statistics only,
  3243.  *                but TRUE if doing data decompression).
  3244.  *
  3245.  *
  3246.  * Description:
  3247.  *              Set the I/O filters for this message handle. A default
  3248.  *              value (no filter) is set up at the time when the message
  3249.  *              handle is created.
  3250.  *
  3251.  * Note:
  3252.  *              It is the responsibility of the higher-level software (i.e.,
  3253.  *              not this module) to free any data associated with ex_proc.
  3254.  */
  3255.  
  3256. void
  3257. MsgSetFilters(MHandPtr mh, VoidPtr ex_proc, NI_WriteFilt wfilt,
  3258.               NI_ReadFilt rfilt, Boolean wfilt_pass, Boolean rfilt_pass)
  3259. {
  3260.     if (mh == NULL)
  3261.         return;
  3262.  
  3263.     mh->extra_proc_info = ex_proc;
  3264.     mh->write_filter = wfilt;
  3265.     mh->read_filter = rfilt;
  3266.     mh->write_filt_pass_thru = wfilt_pass;
  3267.     mh->read_filt_pass_thru = rfilt_pass;
  3268. }
  3269.  
  3270.  
  3271. /*
  3272.  * Purpose:     Set the timeout hooks for this message handle
  3273.  *
  3274.  * Parameters:
  3275.  *   mh           A pointer to the message handle for which the parameters
  3276.  *                are to be set.
  3277.  *
  3278.  *   rhook        A hook to be called when the read timeout expires
  3279.  *
  3280.  *   whook        A hook to be called when the write timeout expires
  3281.  *
  3282.  *
  3283.  * Description:
  3284.  *              Set the read and write timeout hooks for this message handle.
  3285.  *              A default value (no hook) is set up at the time when the
  3286.  *              message handle is created.
  3287.  *
  3288.  * Note:
  3289.  *              The write hook is currently usused (6/2/93).
  3290.  */
  3291.  
  3292. void
  3293. MsgSetTimeoutHooks(MHandPtr mh, NI_TimeoutHook rhook, NI_TimeoutHook whook)
  3294. {
  3295.     if (mh == NULL)
  3296.         return;
  3297.  
  3298.     mh->readTimeoutHook = rhook;
  3299.     mh->writeTimeoutHook = whook;
  3300. }
  3301.  
  3302. /*
  3303.  * Purpose:     Initialize the ASN.1 object loader for this module
  3304.  *
  3305.  * Parameters:
  3306.  *   none
  3307.  *
  3308.  *
  3309.  * Description:
  3310.  *              Dynamically load the ASN.1 static header, if necessary.
  3311.  */
  3312.  
  3313. static Boolean
  3314. InitMsg (void)
  3315. {
  3316.     static Boolean loaded = FALSE;
  3317.  
  3318.     if (loaded)
  3319.         return TRUE;
  3320.     if (! AsnLoad()) 
  3321.         return FALSE;
  3322.     loaded = TRUE;
  3323.     return TRUE;
  3324. }
  3325.  
  3326.  
  3327. /******************************************************************************/
  3328. /*                                                                            */
  3329. /*      Functions used by AsnTool for socket IO (readfunc and writefunc)      */
  3330. /*                                                                            */
  3331. /******************************************************************************/
  3332.  
  3333. /*
  3334.  * Purpose:     Read some data on behalf of the ASN.1 library
  3335.  *
  3336.  * Parameters:
  3337.  *   p            A pointer to the message handle structure
  3338.  *   buf          The buffer into which the data should be read
  3339.  *   len          Maximum number of bytes to be read
  3340.  *
  3341.  * Returns:
  3342.  *                0, if operating in "unblocked mode", and are unable to
  3343.  *                   read the requested amount of data
  3344.  *                -ETIMEOUT, if blocked, waiting for data to be available, but
  3345.  *                   none arrived before the read timeout expired
  3346.  *                -errno [ system error number ], for other errors
  3347.  *                the number of bytes read, otherwise
  3348.  *
  3349.  *
  3350.  * Description:
  3351.  *              This is the 'readfunc' function used by ASN.1 to read some
  3352.  *              data from the specified ASN.1 I/O stream.
  3353.  *
  3354.  *              First, try to read some data from the "queued data", i.e.,
  3355.  *              data which was read from the socket on a previous iteration,
  3356.  *              but ASN.1 processing failed because there was insufficient
  3357.  *              data.
  3358.  *
  3359.  *              Subsequently, try to read from the socket. If the data is
  3360.  *              unavailable, and running in "blocked" mode, wait for either
  3361.  *              the data to appear or for the read timeout to expire.
  3362.  *
  3363.  *              In the case where data is read successfully, store it in
  3364.  *              the "queued data" area.
  3365.  *
  3366.  *              Once data has been read successfully, optionally post-process
  3367.  *              it through a filter routine. This routine may, e.g., collect
  3368.  *              statistics or provide a de-compression mechanism. If it is
  3369.  *              a de-compression mechanism, any data which would not fit in
  3370.  *              the original buffer is stored in the "queued data" area, to
  3371.  *              be re-read by the next call to this function.
  3372.  */
  3373.  
  3374. Int2 LIBCALLBACK
  3375. NI_AsnRead(Pointer p, CharPtr buf, Uint2 len)
  3376. {
  3377.     MHandPtr        mh;
  3378.     int     bytesread;
  3379.     int     ready;
  3380.     time_t  secs0, secs1;
  3381.     fd_set  rfds;
  3382.     struct timeval  timeout;
  3383.     CharPtr extra_buf;
  3384.     Int4 extra_buf_len;
  3385.     CharPtr extra_encr_buf;
  3386.     Int4 extra_encr_buf_len;
  3387.     NI_NetServHook activityHook;
  3388.  
  3389.     mh = (MHandPtr) p;
  3390.  
  3391.     /* always provide caller with queued data, if available */
  3392.     if (MsgHaveSavedData(mh))
  3393.     {
  3394.         return MsgReadSavedData(mh, buf, len);
  3395.     }
  3396.  
  3397.     mh->access_time = time(NULL);
  3398.  
  3399.     DisabVibrant();
  3400.  
  3401.     while ((bytesread = NI_READSOCKET(mh->sok, buf, len)) <= 0) {
  3402. #ifndef NETP_INET_PCNFS
  3403.         if (bytesread == 0) {
  3404.             break;
  3405.         }
  3406. #else
  3407.         SOCK_ERRNO = tk_geterrno (mh->sok);
  3408. #endif
  3409. #ifdef NETP_INET_NEWT
  3410.         SOCK_ERRNO = ABS(bytesread);
  3411. #endif
  3412.         switch (SOCK_ERRNO) {
  3413.           case EINTR:
  3414.             continue;
  3415.  
  3416.           case EAGAIN:
  3417. #if EAGAIN != EWOULDBLOCK
  3418.           case EWOULDBLOCK:
  3419. #endif /* EAGAIN != EWOULDBLOCK */
  3420.             if (mh->unblocked_mode)
  3421.             {
  3422.                 mh->have_blocked = TRUE;
  3423.                 EnabVibrant();
  3424.                 return 0;
  3425.             }
  3426.             FD_ZERO(&rfds);
  3427.             FD_SET(mh->sok, &rfds);
  3428.             secs0 = secs1 = time(NULL);
  3429.  
  3430.               RepeatSelect:
  3431.             /* a simple poll is effected when timeout.tv_sec == 0 */
  3432.             timeout.tv_sec = mh->r_timeout - (secs1 - secs0);
  3433.             timeout.tv_usec = 0;
  3434.             ready = NI_select(mh->sok + 1, &rfds, NULL, NULL, &timeout);
  3435.             if (ready > 0)
  3436.                 continue;
  3437.             if (ready == 0)
  3438.             {
  3439.                 EnabVibrant();
  3440.                 return (-ABS(ETIMEDOUT));
  3441.             }
  3442.             switch (SOCK_ERRNO) {
  3443.               case EINTR:
  3444.                 /* update the timeout because select() does not */
  3445.                 secs1 = time(NULL);
  3446.                 if (secs1 - secs0 > (time_t) mh->r_timeout)
  3447.                 secs1 = secs0 + mh->r_timeout;
  3448.                 goto RepeatSelect;
  3449.  
  3450.               default:
  3451.                 break;
  3452.             }
  3453.             EnabVibrant();
  3454.             return (-ABS(SOCK_ERRNO));
  3455.  
  3456.           default:
  3457.             EnabVibrant();
  3458.             return (-ABS(SOCK_ERRNO));
  3459.         }
  3460. #ifdef WIN16
  3461. #ifdef NETP_INET_WSOCK
  3462.         {
  3463.             MSG msg;
  3464.  
  3465.             if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  3466.             {
  3467.                 TranslateMessage(&msg);
  3468.                 DispatchMessage(&msg);
  3469.             }
  3470.         }
  3471. #else
  3472.         Yield();
  3473. #endif
  3474. #endif
  3475.     }
  3476.  
  3477.     EnabVibrant();
  3478.  
  3479.     extra_buf = NULL;
  3480.     extra_encr_buf = NULL;
  3481.     if (mh->read_filter != NULL)
  3482.     {
  3483.         if (mh->read_filt_pass_thru)
  3484.         {
  3485.             mh->read_filter (mh, buf, bytesread, len, NULL, NULL);
  3486.         }
  3487.         else {
  3488.             bytesread = (int) mh->read_filter (mh, buf, bytesread, len,
  3489.                                                &extra_buf, &extra_buf_len);
  3490.         }
  3491.     }
  3492.  
  3493.     if (mh->encryption != NULL && mh->encryption->read_filter != NULL)
  3494.     {
  3495.         bytesread = (int) mh->encryption->read_filter (mh, buf, bytesread,
  3496.                                                        len, &extra_encr_buf,
  3497.                                                        &extra_encr_buf_len);
  3498.     }
  3499.  
  3500.     if ((activityHook = NI_ActivityHook()) != NULL)
  3501.     {
  3502.         activityHook (mh, NetServHook_read, bytesread);
  3503.     }
  3504.  
  3505.     /* save what we just read */
  3506.     MsgSaveData (mh, buf, bytesread);
  3507.  
  3508.     if (extra_buf != NULL)
  3509.     { /* there was some extra data which we didn't get to read */
  3510.        MsgSaveData (mh, extra_buf, (Uint2) extra_buf_len);
  3511.        mh->cur_index -= extra_buf_len; /* enqueue data for next read */
  3512.        MemFree (extra_buf);
  3513.        extra_buf = NULL;
  3514.     }
  3515.  
  3516.     if (extra_encr_buf != NULL)
  3517.     { /* there was some extra encrypted data which we didn't get to read */
  3518.        MsgSaveData (mh, extra_encr_buf, (Uint2) extra_encr_buf_len);
  3519.        mh->cur_index -= extra_encr_buf_len; /* enqueue data for next read */
  3520.        MemFree (extra_encr_buf);
  3521.        extra_encr_buf = NULL;
  3522.     }
  3523.  
  3524.     return bytesread;
  3525. } /* NI_AsnRead */
  3526.  
  3527.  
  3528.  
  3529. /*
  3530.  * Purpose:     Write some data on behalf of the ASN.1 library
  3531.  *
  3532.  * Parameters:
  3533.  *   p            A pointer to the message handle structure
  3534.  *   buf          The buffer into which the data should be written
  3535.  *   len          Number of bytes to be written
  3536.  *
  3537.  * Returns:
  3538.  *                -ETIMEOUT, if unable to write the data before the write
  3539.  *                   timeout expired
  3540.  *                -errno [ system error number ], for other errors
  3541.  *                the number of bytes written, otherwise
  3542.  *
  3543.  *
  3544.  * Description:
  3545.  *              This is the 'writefunc' function used by ASN.1 to write some
  3546.  *              data to the specified ASN.1 I/O stream.
  3547.  *
  3548.  *              If unable to write the data immediately, block until it is
  3549.  *              possible to write the data, or until the write timeout expires.
  3550.  *
  3551.  *              The data to be output is optionally passed through a filter
  3552.  *              routine. This routine may, for example, collect statistics
  3553.  *              or compress the data to be written.
  3554.  *
  3555.  * Note:
  3556.  *              It is relatively unlikely that "writing" will block, thus
  3557.  *              causing the calling application to block. For "writing" to
  3558.  *              block, there would need to be flow control imposed in the
  3559.  *              TCP/IP protocol suite, which is an unlikely occurance when
  3560.  *              passing small quantities of data.
  3561.  */
  3562.  
  3563. Int2 LIBCALLBACK
  3564. NI_AsnWrite(Pointer p, CharPtr buf, Uint2 len)
  3565. {
  3566.     MHandPtr        mh;
  3567.     Int2    byteswrit, bytesleft;
  3568.     int     ready;
  3569.     fd_set  wfds;
  3570.     time_t  secs0, secs1 = 0;
  3571.     struct timeval  timeout;
  3572.     CharPtr newbuf;
  3573.     Uint2 newlen;
  3574.     CharPtr tmpbuf = NULL;
  3575.     NI_NetServHook activityHook;
  3576.     
  3577.     mh = (MHandPtr) p;
  3578.     mh->access_time = time(NULL);
  3579.  
  3580.     newbuf = buf;
  3581.     newlen = len;
  3582.     if (mh->write_filter != NULL)
  3583.     {
  3584.         if (mh->write_filt_pass_thru)
  3585.         { /* write filter is "pass-through only" */
  3586.             mh->write_filter (mh, buf, len, NULL);
  3587.         }
  3588.         else { /* write filter modifies buffer to be written */
  3589.             tmpbuf = (CharPtr) MemNew(len + 5);
  3590.             newlen = (Uint2) mh->write_filter(mh, buf, len, tmpbuf);
  3591.             newbuf = tmpbuf;
  3592.         }
  3593.     }
  3594.     if (mh->encryption != NULL && mh->encryption->write_filter != NULL)
  3595.     {    
  3596.         tmpbuf = (CharPtr) MemNew(len + 9);
  3597.         newlen = (Uint2) mh->encryption->write_filter(mh, newbuf, newlen, tmpbuf);
  3598.         newbuf = tmpbuf;
  3599.     }
  3600.  
  3601.     if ((activityHook = NI_ActivityHook()) != NULL)
  3602.     {
  3603.         activityHook (mh, NetServHook_write, newlen);
  3604.     }
  3605.  
  3606.     DisabVibrant();
  3607.     
  3608.     for (bytesleft = newlen; bytesleft > 0; bytesleft -= byteswrit,
  3609.          newbuf += byteswrit) {
  3610.         while ((byteswrit = NI_WRITESOCKET(mh->sok, newbuf, bytesleft)) <= 0) {
  3611.         if (byteswrit == 0)
  3612.         {
  3613. #ifdef NETP_INET_NEWT
  3614.             /* this is a real kludge to deal with the fact that NEWT          */
  3615.             /* sometimes returns 0 on a send() for no good reason; we simulate*/
  3616.             /* that we were told that the send() would block                  */
  3617.             byteswrit = -EWOULDBLOCK;
  3618. #else
  3619.             WriteCleanup(tmpbuf);
  3620.             return 0;
  3621. #endif /* NETP_INET_NEWT */
  3622.         }
  3623.  
  3624. #ifdef NETP_INET_NEWT
  3625.         SOCK_ERRNO = ABS(byteswrit);
  3626. #endif
  3627. #ifdef NETP_INET_PCNFS
  3628.         SOCK_ERRNO = tk_geterrno (mh->sok);
  3629. #endif
  3630.  
  3631.         byteswrit = 0; /* don't allow byte count to become messed up */
  3632.  
  3633.         switch (SOCK_ERRNO) {
  3634.           case EINTR:
  3635.             continue;
  3636.             
  3637.           case EAGAIN:
  3638. #if EAGAIN != EWOULDBLOCK
  3639.             
  3640.           case EWOULDBLOCK:
  3641. #endif
  3642. #ifdef NETP_INET_NEWT
  3643.             /* work-around for bug in version 2.00 of NEWT; a select()*/
  3644.             /* will never recognize when it's O.K. to write to a      */
  3645.             /* socket                                                 */
  3646.             if (secs1 == 0)
  3647.             {
  3648.                 secs1 = secs0 = time(NULL);
  3649.             }
  3650.             else {
  3651.                 secs1 = time(NULL);
  3652.                 if (secs1 - secs0 > (time_t) mh->w_timeout)
  3653.                 {
  3654.                     WriteCleanup(tmpbuf);
  3655.                     return (-ABS(ETIMEDOUT));
  3656.                 }
  3657.             }
  3658.             break;
  3659. #endif
  3660.             FD_ZERO(&wfds);
  3661.             FD_SET(mh->sok, &wfds);
  3662.             secs0 = secs1 = time(NULL);
  3663.  
  3664.           RepeatSelect:
  3665.             /* a simple poll is effected when timeout.tv_sec == 0 */
  3666.             timeout.tv_sec = mh->w_timeout - (secs1 - secs0);
  3667.             timeout.tv_usec = 0;
  3668.             ready = NI_select(mh->sok + 1, NULL, &wfds, NULL, &timeout);
  3669.             if (ready > 0)
  3670.                 continue;
  3671.             if (ready == 0)
  3672.             {
  3673.                 WriteCleanup(tmpbuf);
  3674.                 return (-ABS(ETIMEDOUT));
  3675.             }
  3676.             switch (SOCK_ERRNO) {
  3677.               case EINTR:
  3678.                 /* update the timeout because select() does not */
  3679.                 secs1 = time(NULL);
  3680.                 if (secs1 - secs0 > (time_t) mh->w_timeout)
  3681.                     secs1 = secs0 + mh->w_timeout;
  3682.                 goto RepeatSelect;
  3683.               default:
  3684.                 break;
  3685.             }
  3686.             WriteCleanup(tmpbuf);
  3687.             return (-ABS(SOCK_ERRNO));
  3688.  
  3689.           default:
  3690.             WriteCleanup(tmpbuf);
  3691.             return (-ABS(SOCK_ERRNO));
  3692.         }
  3693. #ifdef WIN16
  3694. #ifdef NETP_INET_WSOCK
  3695.         {
  3696.             MSG msg;
  3697.  
  3698.             if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  3699.             {
  3700.                 TranslateMessage(&msg);
  3701.                 DispatchMessage(&msg);
  3702.             }
  3703.         }
  3704. #else
  3705.         Yield();
  3706. #endif
  3707. #endif
  3708.         }
  3709.     }
  3710.  
  3711.     WriteCleanup(tmpbuf);
  3712.     return (Int2)len;
  3713. } /* NI_AsnWrite */
  3714.  
  3715.  
  3716. /*
  3717.  * Purpose:     Clean-up for NI_AsnWrite
  3718.  *
  3719.  * Parameters:
  3720.  *   tmpbuf       Temporary buffer to be freed, if non-NULL
  3721.  *
  3722.  *
  3723.  * Description:
  3724.  *              Frees temporary buffer, and re-enables Vibrant for user
  3725.  *              input. Used because there are so many return paths from
  3726.  *              NI_AsnWrite.
  3727.  *
  3728.  */
  3729.  
  3730. static void
  3731. WriteCleanup (CharPtr tmpbuf)
  3732. {
  3733.     if (tmpbuf != NULL)
  3734.     {
  3735.         MemFree (tmpbuf);
  3736.     }
  3737.     EnabVibrant();
  3738. }
  3739.  
  3740.  
  3741. /*
  3742.  * Purpose:     ASN.1 Error handling
  3743.  *
  3744.  * Parameters:
  3745.  *   level        Error code to be returned
  3746.  *   str          Error text generated by ASN.1
  3747.  *
  3748.  *
  3749.  * Description:
  3750.  *              This is the error handling function used by ASN.1; it is called
  3751.  *              when any ASN.1 I/O error occurs.
  3752.  *
  3753.  *              When an ASN.1 I/O error occurs, this function stores the
  3754.  *              error text in a safe place, and "longjumps", returning
  3755.  *              control to a point where setjmp() was last called. This point
  3756.  *              should occur in a relatively high-level function (above the
  3757.  *              ASN.1 library).
  3758.  *
  3759.  * Note:
  3760.  *              Due to the implementation of setjmp()/longjmp(), if level is
  3761.  *              0, then the setjmp() caller will see the value 1; this
  3762.  *              mechanism is used to allow a setjmp() caller to distinguish
  3763.  *              between the case when they have just "set" the jump environment
  3764.  *              (return value == 0), and all other cases.
  3765.  */
  3766.  
  3767. void LIBCALLBACK
  3768. NI_ASNIOError(Int2 level, CharPtr str)
  3769. {
  3770.     StringCpy(ni_errtext, str);
  3771.     LongJump(ni_env, level);
  3772. } /* NI_ASNIOError */
  3773.  
  3774.  
  3775.  
  3776. #if defined(NETP_INET_NEWT) || defined(NETP_INET_WSOCK)
  3777.  
  3778. /*
  3779.  * Purpose:     Implementation of blocked select() for use with NEWT and WSOCK
  3780.  *
  3781.  * Parameters:
  3782.  *   width        "width" of file descriptor bits maps
  3783.  *   rfds         Read file descriptor bit maps
  3784.  *   wfds         Write file descriptor bit maps
  3785.  *   xfds         Exception file descriptor bit maps
  3786.  *
  3787.  * Returns:
  3788.  *                0, if the timeout period elapses
  3789.  *                -1, if an error occurred
  3790.  *                the number of available file descriptors (selected file
  3791.  *                  descriptors which are available for processing), otherwise
  3792.  *
  3793.  *
  3794.  * Description:
  3795.  *              Provide a "blocked" select() mechanism, because NEWT does
  3796.  *              not provide one.
  3797.  *
  3798.  * Note:
  3799.  *              When calling select(), the width of the file descriptor
  3800.  *              maps is increased by one, to handle an off-by-one error
  3801.  *              associated with the NEWT library.
  3802.  *
  3803.  *              This function is used in WinSock (rather than WinSock's
  3804.  *              select function) to ensure that message removal/dispatching
  3805.  *              is done in a manner which does not interfere with scrollbar
  3806.  *              management.
  3807.  */
  3808.  
  3809. int 
  3810. NI_poll_select(int width, fd_set PNTR rfds, fd_set PNTR wfds, fd_set PNTR xfds, struct timeval PNTR timeout)
  3811. {
  3812.     fd_set      trfds, twfds, txfds;
  3813.     int         rdy;
  3814.     time_t      t_end;
  3815.     struct timeval tmout;
  3816.     
  3817.     if (rfds != NULL)
  3818.         Nlm_MemCopy(&trfds, rfds, sizeof(trfds));
  3819.     if (wfds != NULL)
  3820.         Nlm_MemCopy(&twfds, wfds, sizeof(twfds));
  3821.     if (xfds != NULL)
  3822.         Nlm_MemCopy(&txfds, xfds, sizeof(txfds));
  3823.     
  3824.     t_end = timeout->tv_sec + Nlm_GetSecs();
  3825.     tmout.tv_sec = 0;
  3826.     tmout.tv_usec = 0;
  3827. #ifdef NETP_INET_WSOCK
  3828.     width--;
  3829. #endif
  3830.     while  (Nlm_GetSecs() < t_end) {
  3831.         if (rfds != NULL)
  3832.             Nlm_MemCopy(rfds, &trfds, sizeof(trfds));
  3833.         if (wfds != NULL)
  3834.             Nlm_MemCopy(wfds, &twfds, sizeof(twfds));
  3835.         if (xfds != NULL)
  3836.             Nlm_MemCopy(xfds, &txfds, sizeof(txfds));
  3837.         
  3838. #ifdef NETP_INET_WSOCK
  3839.         {
  3840.             MSG msg;
  3841.             Boolean done = FALSE;
  3842.  
  3843.             /* get all the available messages, avoiding WM_LBUTTONUP since  */
  3844.             /* this will cause scroll bars to hang, for some unknown reason */
  3845.             while (! done)
  3846.             {
  3847.                 done = TRUE;
  3848.                 if (PeekMessage(&msg, NULL, 0, WM_LBUTTONUP-1, PM_REMOVE))
  3849.                 {
  3850.                     done = FALSE;
  3851.                     TranslateMessage(&msg);
  3852.                     DispatchMessage(&msg);
  3853.                 }
  3854.                 if (PeekMessage(&msg, NULL, WM_LBUTTONUP+1, 0xffff, PM_REMOVE))
  3855.                 {
  3856.                     done = FALSE;
  3857.                     TranslateMessage(&msg);
  3858.                     DispatchMessage(&msg);
  3859.                 }
  3860.             }
  3861.         }
  3862. #else
  3863. #ifdef WIN16
  3864.         Yield();
  3865. #endif
  3866. #endif
  3867.         /* select with (width + 1) because NetManage boundary condition error */
  3868.         
  3869.         if ((rdy = select((width + 1), rfds, wfds, xfds, &tmout)) != 0) {
  3870.             if (rdy < 0) {              /* error */
  3871. #ifdef NETP_INET_NEWT
  3872.                 errno = ABS(rdy);
  3873. #endif
  3874.                 rdy = -1;
  3875.             }
  3876.             return rdy;
  3877.         }
  3878.  
  3879.     }
  3880.     return 0;   /* timed out */
  3881. } /* NI_poll_select */
  3882.  
  3883. #endif
  3884.  
  3885.  
  3886. #ifdef NI_BLOCK_WITH_FUNCTION
  3887.  
  3888.  
  3889. /*
  3890.  * Purpose:     Implementation of setting non-blocked-socket mode for platforms
  3891.  *              for which it is difficult to perform this functionality within
  3892.  *              a macro.
  3893.  *
  3894.  * Parameters:
  3895.  *   fd           Socket file descriptor
  3896.  *
  3897.  */
  3898.  
  3899. int
  3900. NI_SetNonBlocking (int fd)
  3901. {
  3902.   int mode = 1;
  3903.  
  3904. #ifdef NETP_INET_WSOCK
  3905.   u_long lmode = 1;
  3906.   return ioctlsocket (fd, FIONBIO, &lmode);
  3907. #endif
  3908.  
  3909. #ifdef NETP_INET_PCNFS
  3910.   return tk_ioctl (fd, FIONBIO, &mode);
  3911. #endif
  3912. #ifdef NETP_INET_TGV
  3913.   return socket_ioctl (fd, FIONBIO, &mode); 
  3914. #endif
  3915. #ifdef NETP_INET_WPW
  3916.   long lmode = 0;
  3917.   return ioctl (fd, FIONBIO, &mode); 
  3918. #endif
  3919. #ifdef NETP_INET_TWG
  3920.   /**************************************************************************/
  3921.   /* WARNING: THIS IS CURRENTLY NOT IMPLEMENTED PROPERLY BECAUSE WE (W.     */
  3922.   /*          GILBERT/J. EPSTEIN) ARE NOT ABLE TO MAKE NETWORK SERVICES     */
  3923.   /*          OPERATE PROPERLY IN NON-BLOCKING MODE.  AT SOME FUTURE DATE,  */
  3924.   /*          THE REMAINDER OF NETWORK SERVICES SHOULD BE DEBUGGED AND THE  */
  3925.   /*          FOLLOWING LINE SHOULD READ: lmode = 1                         */
  3926.   /*                                          17 June 1993                  */
  3927.   /**************************************************************************/
  3928.   /*
  3929.   long lmode = 0;
  3930.   return ioctl (fd, FIONBIO, &lmode);
  3931.  */
  3932.   return 0;
  3933. #endif
  3934. #ifdef NETP_INET_UCX
  3935.   /**************************************************************************/
  3936.   /* WARNING: THIS IS CURRENTLY UNIMPLEMENTED BECAUSE IT IS NOT CLEAR THAT  */
  3937.   /*          IT IS POSSIBLE TO SPECIFY BLOCKING/NONBLOCKING MODE FOR UCX   */
  3938.   /*                                          22 June 1993                  */
  3939.   /**************************************************************************/
  3940.   return 0;
  3941. #endif
  3942. }
  3943.  
  3944. /*
  3945.  * Purpose:     Implementation of setting blocked-socket mode for platforms
  3946.  *              for which it is difficult to perform this functionality within
  3947.  *              a macro.
  3948.  *
  3949.  * Parameters:
  3950.  *   fd           Socket file descriptor
  3951.  *
  3952.  */
  3953.  
  3954. int
  3955. NI_SetBlocking (int fd)
  3956. {
  3957.   int mode = 0;
  3958.  
  3959. #ifdef NETP_INET_WSOCK
  3960.   u_long lmode = 0;
  3961.   return ioctlsocket (fd, FIONBIO, &lmode);
  3962. #endif
  3963.  
  3964. #ifdef NETP_INET_PCNFS
  3965.   return tk_ioctl (fd, FIONBIO, &mode);
  3966. #endif
  3967. #ifdef NETP_INET_TGV
  3968.   return socket_ioctl (fd, FIONBIO, &mode);
  3969. #endif
  3970. #ifdef NETP_INET_WPW
  3971.   long lmode = 0;
  3972.   return ioctl (fd, FIONBIO, &lmode);
  3973. #endif
  3974. #ifdef NETP_INET_TWG
  3975.   /*
  3976.   long lmode = 0;
  3977.   return ioctl (fd, FIONBIO, &lmode);
  3978. */
  3979.   return 0;
  3980. #endif
  3981. #ifdef NETP_INET_UCX
  3982.   /**************************************************************************/
  3983.   /* WARNING: THIS IS CURRENTLY UNIMPLEMENTED BECAUSE IT IS NOT CLEAR THAT  */
  3984.   /*          IT IS POSSIBLE TO SPECIFY BLOCKING/NONBLOCKING MODE FOR UCX   */
  3985.   /*                                          22 June 1993                  */
  3986.   /**************************************************************************/
  3987.   return 0;
  3988. #endif
  3989. }
  3990.  
  3991. #endif /* BLOCK_WITH_FUNCTION */
  3992.  
  3993.  
  3994. /*
  3995.  * Purpose:     Test as to whether there's available data already enqueued
  3996.  *
  3997.  * Parameters:
  3998.  *   mh           Pointer to "message handle" data structure
  3999.  *
  4000.  * Returns:
  4001.  *                FALSE, if there is no data already enqueued
  4002.  *                TRUE, otherwise
  4003.  *
  4004.  *
  4005.  * Description:
  4006.  *              Determine whether there is currently enqueued data on a
  4007.  *              "message handle" data structure.
  4008.  */
  4009.  
  4010. static Boolean
  4011. MsgHaveSavedData(MHandPtr mh)
  4012. {
  4013.     if (!mh->unblocked_mode)
  4014.         return FALSE;
  4015.     if (mh->queued_data_list == NULL)
  4016.         return FALSE;
  4017.     if (mh->num_queued_bytes <= 0)
  4018.         return FALSE;
  4019.     return (mh->cur_index < mh->num_queued_bytes);
  4020. }
  4021.  
  4022.  
  4023. /*
  4024.  * Purpose:     Read data which was previously stored in this "message handle"
  4025.  *
  4026.  * Parameters:
  4027.  *   mh           Pointer to "message handle" data structure
  4028.  *   buf          Buffer where data should be stored
  4029.  *   len          Maximum number of bytes to read out
  4030.  *
  4031.  * Returns:
  4032.  *                the number of bytes read from the enqueued data list
  4033.  *
  4034.  *
  4035.  * Description:
  4036.  *              Return up to len bytes of enqueued data, by traversing
  4037.  *              the enqueued data structure, beginning with the location
  4038.  *              where the "current byte" pointer is currently pointing.
  4039.  *
  4040.  * Note:
  4041.  *              The enqueued data is stored in a list of chained blocks, where
  4042.  *              at all times, all the blocks are full, except (possibly) the
  4043.  *              last block.
  4044.  */
  4045.  
  4046. #define MSG_READ_BLOCK_SIZE 1024
  4047.  
  4048. static int
  4049. MsgReadSavedData(MHandPtr mh, CharPtr buf, Uint2 len)
  4050. {
  4051.     NodePtr startpt;
  4052.     NodePtr blk;
  4053.     int     addl_queue_data;
  4054.     int     local_index;
  4055.     int     bytes_copied;
  4056.     int     data_in_this_block;
  4057.     int     bytes_to_copy;
  4058.  
  4059.     if (mh->queued_data_list == NULL || len <= 0 || mh->num_queued_bytes == 0)
  4060.         return 0;
  4061.     blk = startpt = mh->queued_data_list;
  4062.     addl_queue_data = mh->num_queued_bytes - mh->cur_index;
  4063.     local_index = 0;
  4064.     bytes_copied = 0;
  4065.  
  4066.     /* traverse the portion of the list which is necessary to get past */
  4067.     /* the current "file" pointer, and then copy up to len bytes of    */
  4068.     /* data from the remaining blocks                                  */
  4069.     do {
  4070.         /* if ( this is the last block ) then */
  4071.         if (mh->num_queued_bytes - local_index < MSG_READ_BLOCK_SIZE)
  4072.             data_in_this_block = mh->num_queued_bytes % MSG_READ_BLOCK_SIZE;
  4073.         else
  4074.             data_in_this_block = MSG_READ_BLOCK_SIZE;
  4075.  
  4076.         /* if ( there is more data to be skipped over ) then */
  4077.         if (local_index < mh->cur_index)
  4078.         { /* there is more data to be skipped over */
  4079.             if (local_index + data_in_this_block <= mh->cur_index)
  4080.             { /* skip this block */
  4081.                 local_index += data_in_this_block;
  4082.                 continue;
  4083.             }
  4084.             else { /* skip a portion of this block, and copy the remainder */
  4085.                 data_in_this_block -= (mh->cur_index - local_index);
  4086.                 local_index = mh->cur_index;
  4087.             }
  4088.         }
  4089.  
  4090.         bytes_to_copy = MIN((int) len, data_in_this_block);
  4091.         MemCopy(buf, blk->elem, bytes_to_copy);
  4092.         buf += bytes_to_copy;
  4093.         len -= bytes_to_copy;
  4094.         bytes_copied += bytes_to_copy;
  4095.         mh->cur_index += bytes_to_copy;
  4096.         local_index += bytes_to_copy;
  4097.     } while ( (blk = ListGetNext(blk)) != startpt && len > 0);
  4098.  
  4099.     return bytes_copied;
  4100. }
  4101.  
  4102.  
  4103.  
  4104. /*
  4105.  * Purpose:     Store len bytes of data from a buffer, for future use
  4106.  *
  4107.  * Parameters:
  4108.  *   mh           Pointer to "message handle" data structure
  4109.  *   buf          Buffer of data to be copied
  4110.  *   len          Number of bytes to save
  4111.  *
  4112.  *
  4113.  * Description:
  4114.  *              Store len bytes of data at the end of a list of "enqueued data."
  4115.  *              After finding the current end of the queue, data is added
  4116.  *              to the final block (up to its capacity), and then, if needed,
  4117.  *              additional blocks are allocated to store the remaining data.
  4118.  */
  4119.  
  4120. static void
  4121. MsgSaveData(MHandPtr mh, CharPtr buf, Uint2 len)
  4122. {
  4123.     NodePtr tail;
  4124.     int     bytes_to_copy;
  4125.     int     starting_byte;
  4126.     CharPtr newdata;
  4127.  
  4128.     if (len == 0 || !mh->unblocked_mode)
  4129.         return;
  4130.  
  4131.     /* get to the correct place in the list, and then start storing */
  4132.  
  4133.     tail = mh->queued_data_list;
  4134.  
  4135.     /* point to tail of list; in a ring, the element before the head is the */
  4136.     /* tail                                                                 */
  4137.     if (tail != NULL)
  4138.         tail = tail->last;
  4139.  
  4140.     /* if ( more room in the current element ) then */
  4141.     if ((starting_byte = mh->num_queued_bytes % MSG_READ_BLOCK_SIZE) != 0)
  4142.     {
  4143.         bytes_to_copy = MIN(MSG_READ_BLOCK_SIZE - starting_byte, (int) len);
  4144.         newdata = (CharPtr) tail->elem;
  4145.         MemCopy (&newdata[starting_byte], buf, bytes_to_copy);
  4146.         len -= bytes_to_copy;
  4147.         buf += len;
  4148.         mh->num_queued_bytes += bytes_to_copy;
  4149.     }
  4150.  
  4151.     /* while ( there is more data to be copied ) */
  4152.     while (len > 0)
  4153.     { /* create a new element, and copy data into that element */
  4154.  
  4155.         newdata = MemNew(MSG_READ_BLOCK_SIZE);
  4156.         bytes_to_copy = MIN(MSG_READ_BLOCK_SIZE, len);
  4157.         MemCopy (newdata, buf, bytes_to_copy);
  4158.         buf += bytes_to_copy;
  4159.         len -= bytes_to_copy;
  4160.         mh->num_queued_bytes += bytes_to_copy;
  4161.         tail = ListInsert(newdata, tail);
  4162.     }
  4163.  
  4164.     mh->cur_index = mh->num_queued_bytes;
  4165.  
  4166.     if (tail == NULL)
  4167.         mh->queued_data_list = NULL;
  4168.     else
  4169.         mh->queued_data_list = tail->next;
  4170. }
  4171.  
  4172.  
  4173.  
  4174. /*
  4175.  * Purpose:     Free data associated with an "enqueued data list"
  4176.  *
  4177.  * Parameters:
  4178.  *   mh           Pointer to "message handle" data structure
  4179.  *
  4180.  *
  4181.  * Description:
  4182.  *              Free all the message elements associated with a list of
  4183.  *              enqueued data, and set other message handle elements to
  4184.  *              appropriate values such that software accessing those structures
  4185.  *              will not, erroneously, think that there is valid enqueued data
  4186.  *              in the structure.
  4187.  */
  4188.  
  4189. static void
  4190. MsgFreeSavedData (MHandPtr mh)
  4191. {
  4192.     NodePtr np;
  4193.     CharPtr elem;
  4194.  
  4195.     mh->unblocked_mode = FALSE;
  4196.     mh->have_blocked = FALSE;
  4197.     mh->num_queued_bytes = 0;
  4198.     mh->cur_index = 0;
  4199.  
  4200.     np = mh->queued_data_list;
  4201.  
  4202.     mh->queued_data_list = NULL;
  4203.  
  4204.     while (np != NULL)
  4205.     {
  4206.         elem = (CharPtr) np->elem;
  4207.         if (elem != NULL)
  4208.             MemFree (elem);
  4209.         np = ListDelete(np);
  4210.     }
  4211. }
  4212.  
  4213.  
  4214. /*
  4215.  * Purpose:     Set and pop the hour-glass cursor
  4216.  *
  4217.  * Parameters:
  4218.  *   none
  4219.  *
  4220.  * Description:
  4221.  *              According to the NEWT/NetManage documentation, it is
  4222.  *              beneficial to make the cursor into an hourglass to block-out
  4223.  *              unwanted events during some socket calls.
  4224.  */
  4225.  
  4226. #if defined(NETP_INET_NEWT) || defined(NETP_INET_WSOCK)
  4227. static HCURSOR saveCursor = NULL;
  4228.  
  4229. static void SetHourGlass(void)
  4230. {
  4231. #ifdef NETP_INET_NEWT
  4232.    static HCURSOR hourCursor;
  4233.  
  4234.    hourCursor = LoadCursor(NULL, IDC_WAIT);
  4235.    saveCursor = SetCursor(hourCursor);
  4236. #endif
  4237. }
  4238.  
  4239. static void PopHourGlass(void)
  4240. {
  4241. #ifdef NETP_INET_NEWT
  4242.    if (saveCursor != NULL)
  4243.       SetCursor(saveCursor);
  4244. #endif
  4245. }
  4246. #endif /* NETP_INET_NEWT */
  4247.  
  4248.